Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
807058e40d | ||
|
|
c6022b0e22 | ||
|
|
9aed6e0d43 | ||
|
|
64b664e625 | ||
|
|
49f1a2fbf2 | ||
|
|
6bfe890cd9 |
@@ -131,16 +131,16 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
|
|
||||||
protected componentCollection = [
|
protected componentCollection = [
|
||||||
{ name: "Common Filter", componentInstance: CommonFilterComponent },
|
{ name: "Common Filter", componentInstance: CommonFilterComponent },
|
||||||
{ name: "Line Chart", componentInstance: LineChartComponent },
|
{ name: "Line Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Doughnut Chart", componentInstance: DoughnutChartComponent },
|
{ name: "Doughnut Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Radar Chart", componentInstance: RadarChartComponent },
|
{ name: "Radar Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Bar Chart", componentInstance: BarChartComponent },
|
{ name: "Bar Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Pie Chart", componentInstance: PieChartComponent },
|
{ name: "Pie Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Polar Area Chart", componentInstance: PolarChartComponent },
|
{ name: "Polar Area Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Bubble Chart", componentInstance: BubbleChartComponent },
|
{ name: "Bubble Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Scatter Chart", componentInstance: ScatterChartComponent },
|
{ name: "Scatter Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Dynamic Chart", componentInstance: DynamicChartComponent },
|
{ name: "Dynamic Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "Financial Chart", componentInstance: FinancialChartComponent },
|
{ name: "Financial Chart", componentInstance: UnifiedChartComponent },
|
||||||
{ name: "To Do Chart", componentInstance: ToDoChartComponent },
|
{ name: "To Do Chart", componentInstance: ToDoChartComponent },
|
||||||
{ name: "Grid View", componentInstance: GridViewComponent },
|
{ name: "Grid View", componentInstance: GridViewComponent },
|
||||||
{ name: "Compact Filter", componentInstance: CompactFilterComponent },
|
{ name: "Compact Filter", componentInstance: CompactFilterComponent },
|
||||||
@@ -393,6 +393,27 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Map chart names to unified chart types
|
||||||
|
const chartTypeMap = {
|
||||||
|
'Radar Chart': 'radar',
|
||||||
|
'Line Chart': 'line',
|
||||||
|
'Doughnut Chart': 'doughnut',
|
||||||
|
'Bar Chart': 'bar',
|
||||||
|
'Pie Chart': 'pie',
|
||||||
|
'Polar Area Chart': 'polar',
|
||||||
|
'Bubble Chart': 'bubble',
|
||||||
|
'Scatter Chart': 'scatter',
|
||||||
|
'Dynamic Chart': 'line',
|
||||||
|
'Financial Chart': 'line'
|
||||||
|
};
|
||||||
|
|
||||||
|
// If this is a chart, set the chartType property
|
||||||
|
if (chartTypeMap.hasOwnProperty(dashboard.name)) {
|
||||||
|
dashboard.chartType = chartTypeMap[dashboard.name];
|
||||||
|
// Keep the original name instead of changing it to "Unified Chart"
|
||||||
|
// dashboard.name = "Unified Chart";
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure compact filter configuration properties are properly initialized
|
// Ensure compact filter configuration properties are properly initialized
|
||||||
if (dashboard.component === 'Compact Filter' || dashboard.name === 'Compact Filter') {
|
if (dashboard.component === 'Compact Filter' || dashboard.name === 'Compact Filter') {
|
||||||
// Make sure all compact filter properties exist
|
// Make sure all compact filter properties exist
|
||||||
@@ -417,6 +438,29 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Map unified chart types back to chart names for serialization
|
||||||
|
const chartNameMap = {
|
||||||
|
'radar': 'Radar Chart',
|
||||||
|
'line': 'Line Chart',
|
||||||
|
'doughnut': 'Doughnut Chart',
|
||||||
|
'bar': 'Bar Chart',
|
||||||
|
'pie': 'Pie Chart',
|
||||||
|
'polar': 'Polar Area Chart',
|
||||||
|
'bubble': 'Bubble Chart',
|
||||||
|
'scatter': 'Scatter Chart'
|
||||||
|
};
|
||||||
|
|
||||||
|
// If this is a unified chart, set the name back to the appropriate chart name
|
||||||
|
if (dashboard.name === 'Unified Chart' && dashboard.chartType && chartNameMap.hasOwnProperty(dashboard.chartType)) {
|
||||||
|
dashboard.name = chartNameMap[dashboard.chartType];
|
||||||
|
}
|
||||||
|
// Also handle the case where the chart already has the correct name
|
||||||
|
else if (dashboard.chartType && chartNameMap.hasOwnProperty(dashboard.chartType) &&
|
||||||
|
dashboard.name === chartNameMap[dashboard.chartType]) {
|
||||||
|
// The name is already correct, no need to change it
|
||||||
|
dashboard.component = "Unified Chart";
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure compact filter configuration properties are preserved
|
// Ensure compact filter configuration properties are preserved
|
||||||
if (dashboard.name === 'Compact Filter') {
|
if (dashboard.name === 'Compact Filter') {
|
||||||
// Make sure all compact filter properties exist
|
// Make sure all compact filter properties exist
|
||||||
@@ -428,6 +472,7 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add method to get available fields for a filter dropdown (excluding already selected fields)
|
// Add method to get available fields for a filter dropdown (excluding already selected fields)
|
||||||
getAvailableFields(filters: any[], currentIndex: number, allFields: string[]): string[] {
|
getAvailableFields(filters: any[], currentIndex: number, allFields: string[]): string[] {
|
||||||
if (!filters || !allFields) {
|
if (!filters || !allFields) {
|
||||||
@@ -473,6 +518,7 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (componentType) {
|
switch (componentType) {
|
||||||
|
// Handle all chart types by converting them to unified charts
|
||||||
case "radar_chart":
|
case "radar_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
cols: 5,
|
cols: 5,
|
||||||
@@ -480,8 +526,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: RadarChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Radar Chart"
|
name: "Radar Chart",
|
||||||
|
chartType: 'radar',
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "line_chart":
|
case "line_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -490,8 +541,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: LineChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Line Chart"
|
name: "Line Chart",
|
||||||
|
chartType: 'line',
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "doughnut_chart":
|
case "doughnut_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -500,8 +556,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: DoughnutChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Doughnut Chart"
|
name: "Doughnut Chart",
|
||||||
|
chartType: 'doughnut',
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "bar_chart":
|
case "bar_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -510,8 +571,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: BarChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Bar Chart"
|
name: "Bar Chart",
|
||||||
|
chartType: 'bar',
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "pie_chart":
|
case "pie_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -520,8 +586,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: PieChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Pie Chart"
|
name: "Pie Chart",
|
||||||
|
chartType: 'pie',
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "polar_area_chart":
|
case "polar_area_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -530,8 +601,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: PolarChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Polar Area Chart"
|
name: "Polar Area Chart",
|
||||||
|
chartType: 'polar',
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "bubble_chart":
|
case "bubble_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -540,8 +616,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: BubbleChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Bubble Chart"
|
name: "Bubble Chart",
|
||||||
|
chartType: 'bubble',
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "scatter_chart":
|
case "scatter_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -550,8 +631,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: ScatterChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Scatter Chart"
|
name: "Scatter Chart",
|
||||||
|
chartType: 'scatter',
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "dynamic_chart":
|
case "dynamic_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -560,8 +646,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: DynamicChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Dynamic Chart"
|
name: "Dynamic Chart",
|
||||||
|
chartType: 'line', // Default to line for dynamic chart
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "financial_chart":
|
case "financial_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -570,8 +661,13 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
chartid: maxChartId + 1,
|
chartid: maxChartId + 1,
|
||||||
component: FinancialChartComponent,
|
component: UnifiedChartComponent,
|
||||||
name: "Financial Chart"
|
name: "Financial Chart",
|
||||||
|
chartType: 'line', // Default to line for financial chart
|
||||||
|
xAxis: '',
|
||||||
|
yAxis: '',
|
||||||
|
table: '',
|
||||||
|
connection: undefined
|
||||||
});
|
});
|
||||||
case "to_do_chart":
|
case "to_do_chart":
|
||||||
return this.dashboardArray.push({
|
return this.dashboardArray.push({
|
||||||
@@ -1047,7 +1143,14 @@ export class EditnewdashComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For UnifiedChartComponent, pass chart properties with chartType
|
// For UnifiedChartComponent, pass chart properties with chartType
|
||||||
if (item.name === 'Unified Chart') {
|
// Check for specific chart names that use UnifiedChartComponent
|
||||||
|
const unifiedChartNames = [
|
||||||
|
'Radar Chart', 'Line Chart', 'Doughnut Chart', 'Bar Chart',
|
||||||
|
'Pie Chart', 'Polar Area Chart', 'Bubble Chart', 'Scatter Chart',
|
||||||
|
'Dynamic Chart', 'Financial Chart', 'Unified Chart'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (unifiedChartNames.includes(item.name)) {
|
||||||
const unifiedChartInputs = {
|
const unifiedChartInputs = {
|
||||||
chartType: item.chartType || 'bar',
|
chartType: item.chartType || 'bar',
|
||||||
xAxis: item.xAxis,
|
xAxis: item.xAxis,
|
||||||
|
|||||||
@@ -13,12 +13,25 @@
|
|||||||
<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 -->
|
||||||
<div *ngIf="chartType === 'bar'">
|
<div *ngIf="chartType === 'bar'" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[data]="chartData"
|
[datasets]="chartData"
|
||||||
[labels]="chartLabels"
|
[labels]="chartLabels"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
@@ -29,9 +42,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Line Chart -->
|
<!-- Line Chart -->
|
||||||
<div *ngIf="chartType === 'line'">
|
<div *ngIf="chartType === 'line'" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[data]="chartData"
|
[datasets]="chartData"
|
||||||
[labels]="chartLabels"
|
[labels]="chartLabels"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
@@ -42,9 +55,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Pie Chart -->
|
<!-- Pie Chart -->
|
||||||
<div *ngIf="chartType === 'pie'">
|
<div *ngIf="chartType === 'pie'" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[data]="chartData"
|
[datasets]="chartData"
|
||||||
[labels]="chartLabels"
|
[labels]="chartLabels"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
@@ -55,9 +68,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Doughnut Chart -->
|
<!-- Doughnut Chart -->
|
||||||
<div *ngIf="chartType === 'doughnut'">
|
<div *ngIf="chartType === 'doughnut'" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[data]="chartData"
|
[datasets]="chartData"
|
||||||
[labels]="chartLabels"
|
[labels]="chartLabels"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
@@ -68,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Bubble Chart -->
|
<!-- Bubble Chart -->
|
||||||
<div *ngIf="chartType === 'bubble'">
|
<div *ngIf="chartType === 'bubble'" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[datasets]="bubbleChartData"
|
[datasets]="bubbleChartData"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
@@ -80,9 +93,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Radar Chart -->
|
<!-- Radar Chart -->
|
||||||
<div *ngIf="chartType === 'radar'">
|
<div *ngIf="chartType === 'radar'" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[data]="chartData"
|
[datasets]="chartData"
|
||||||
[labels]="chartLabels"
|
[labels]="chartLabels"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
@@ -93,9 +106,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Polar Area Chart -->
|
<!-- Polar Area Chart -->
|
||||||
<div *ngIf="chartType === 'polar'">
|
<div *ngIf="chartType === 'polar'" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[data]="chartData"
|
[datasets]="chartData"
|
||||||
[labels]="chartLabels"
|
[labels]="chartLabels"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
@@ -106,7 +119,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Scatter Chart -->
|
<!-- Scatter Chart -->
|
||||||
<div *ngIf="chartType === 'scatter'">
|
<div *ngIf="chartType === 'scatter'" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[datasets]="chartData"
|
[datasets]="chartData"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
@@ -118,9 +131,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Default/Unknown Chart Type -->
|
<!-- Default/Unknown Chart Type -->
|
||||||
<div *ngIf="!['bar', 'line', 'pie', 'doughnut', 'bubble', 'radar', 'polar', 'scatter'].includes(chartType)">
|
<div *ngIf="!['bar', 'line', 'pie', 'doughnut', 'bubble', 'radar', 'polar', 'scatter'].includes(chartType)" class="chart-canvas-container">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[data]="chartData"
|
[datasets]="chartData"
|
||||||
[labels]="chartLabels"
|
[labels]="chartLabels"
|
||||||
[options]="chartOptions"
|
[options]="chartOptions"
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -30,7 +30,49 @@
|
|||||||
.chart-wrapper {
|
.chart-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: calc(100% - 100px);
|
height: calc(100% - 100px);
|
||||||
min-height: 300px;
|
min-height: 400px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-canvas-container {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
padding: 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
@@ -246,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;
|
||||||
@@ -259,4 +300,8 @@
|
|||||||
.chart-wrapper {
|
.chart-wrapper {
|
||||||
min-height: 250px;
|
min-height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chart-canvas-container {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
@@ -255,6 +369,8 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.chartOptions = {
|
this.chartOptions = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
|
barPercentage: 0.6, // Reduced from 0.8 to create more spacing between bars
|
||||||
|
categoryPercentage: 0.8, // Reduced from 0.9 to create more spacing between categories
|
||||||
scales: {
|
scales: {
|
||||||
x: {
|
x: {
|
||||||
ticks: {
|
ticks: {
|
||||||
@@ -276,7 +392,9 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
font: {
|
font: {
|
||||||
size: 12
|
size: 12
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
// Add some padding to the y-axis to prevent bars from touching the top
|
||||||
|
suggestedMax: 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
@@ -286,11 +404,21 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
labels: {
|
labels: {
|
||||||
font: {
|
font: {
|
||||||
size: 12
|
size: 12
|
||||||
}
|
},
|
||||||
|
// Add padding to legend items
|
||||||
|
padding: 20
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
enabled: true
|
enabled: true,
|
||||||
|
// Improve tooltip appearance
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
titleFont: {
|
||||||
|
size: 14
|
||||||
|
},
|
||||||
|
bodyFont: {
|
||||||
|
size: 12
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
layout: {
|
layout: {
|
||||||
@@ -300,6 +428,21 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
right: 15,
|
right: 15,
|
||||||
top: 15
|
top: 15
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// Add bar chart specific options
|
||||||
|
indexAxis: 'x', // Horizontal bars
|
||||||
|
elements: {
|
||||||
|
bar: {
|
||||||
|
borderWidth: 2, // Increased border width for better visibility
|
||||||
|
borderSkipped: false, // Show all borders for better separation
|
||||||
|
// Add border color to make bars more distinct
|
||||||
|
borderColor: 'rgba(255, 255, 255, 0.8)' // White border for better separation
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Animation settings for smoother transitions
|
||||||
|
animation: {
|
||||||
|
duration: 1000,
|
||||||
|
easing: 'easeInOutQuart'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -544,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
|
||||||
@@ -1291,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
|
||||||
@@ -1346,4 +1494,255 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if there are active filters
|
||||||
|
hasActiveFilters(): boolean {
|
||||||
|
return (this.baseFilters && this.baseFilters.length > 0) ||
|
||||||
|
(this.drilldownFilters && this.drilldownFilters.length > 0) ||
|
||||||
|
this.hasActiveLayerFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are active layer filters for current drilldown level
|
||||||
|
hasActiveLayerFilters(): boolean {
|
||||||
|
if (this.currentDrilldownLevel > 1 && this.drilldownLayers && this.drilldownLayers.length > 0) {
|
||||||
|
const layerIndex = this.currentDrilldownLevel - 2; // -2 because level 1 is base drilldown
|
||||||
|
return layerIndex < this.drilldownLayers.length &&
|
||||||
|
this.drilldownLayers[layerIndex].filters &&
|
||||||
|
this.drilldownLayers[layerIndex].filters.length > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get active layer filters for current drilldown level
|
||||||
|
getActiveLayerFilters(): any[] {
|
||||||
|
if (this.currentDrilldownLevel > 1 && this.drilldownLayers && this.drilldownLayers.length > 0) {
|
||||||
|
const layerIndex = this.currentDrilldownLevel - 2; // -2 because level 1 is base drilldown
|
||||||
|
if (layerIndex < this.drilldownLayers.length &&
|
||||||
|
this.drilldownLayers[layerIndex].filters) {
|
||||||
|
return this.drilldownLayers[layerIndex].filters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get filter options for dropdown/multiselect filters
|
||||||
|
getFilterOptions(filter: any): string[] {
|
||||||
|
if (filter.options) {
|
||||||
|
if (Array.isArray(filter.options)) {
|
||||||
|
return filter.options;
|
||||||
|
} else if (typeof filter.options === 'string') {
|
||||||
|
return filter.options.split(',').map(opt => opt.trim()).filter(opt => opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if an option is selected for multiselect filters
|
||||||
|
isOptionSelected(filter: any, option: string): boolean {
|
||||||
|
if (!filter.value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(filter.value)) {
|
||||||
|
return filter.value.includes(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter.value === option;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle base filter changes
|
||||||
|
onBaseFilterChange(filter: any): void {
|
||||||
|
console.log('Base filter changed:', filter);
|
||||||
|
// Refresh data when filter changes
|
||||||
|
this.fetchChartData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle drilldown filter changes
|
||||||
|
onDrilldownFilterChange(filter: any): void {
|
||||||
|
console.log('Drilldown filter changed:', filter);
|
||||||
|
// Refresh data when filter changes
|
||||||
|
this.fetchChartData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle layer filter changes
|
||||||
|
onLayerFilterChange(filter: any): void {
|
||||||
|
console.log('Layer filter changed:', filter);
|
||||||
|
// Refresh data when filter changes
|
||||||
|
this.fetchChartData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle multiselect changes
|
||||||
|
onMultiSelectChange(filter: any, option: string, event: any): void {
|
||||||
|
const checked = event.target.checked;
|
||||||
|
|
||||||
|
// Initialize filter.value as array if it's not already
|
||||||
|
if (!Array.isArray(filter.value)) {
|
||||||
|
filter.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checked) {
|
||||||
|
// Add option to array if not already present
|
||||||
|
if (!filter.value.includes(option)) {
|
||||||
|
filter.value.push(option);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Remove option from array
|
||||||
|
filter.value = filter.value.filter((item: string) => item !== option);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh data when filter changes
|
||||||
|
this.fetchChartData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle date range changes
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle toggle changes
|
||||||
|
onToggleChange(filter: any, checked: boolean): void {
|
||||||
|
filter.value = checked;
|
||||||
|
// Refresh data when filter changes
|
||||||
|
this.fetchChartData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle multiselect dropdown visibility
|
||||||
|
toggleMultiselect(filter: any, context: string): void {
|
||||||
|
const filterId = `${context}-${filter.field}`;
|
||||||
|
if (this.isMultiselectOpen(filter, context)) {
|
||||||
|
this.openMultiselects.delete(filterId);
|
||||||
|
} else {
|
||||||
|
// Close all other multiselects first
|
||||||
|
this.openMultiselects.clear();
|
||||||
|
this.openMultiselects.set(filterId, context);
|
||||||
|
|
||||||
|
// Add document click handler to close dropdown when clicking outside
|
||||||
|
this.addDocumentClickHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add document click handler to close dropdowns when clicking outside
|
||||||
|
private addDocumentClickHandler(): void {
|
||||||
|
if (!this.documentClickHandler) {
|
||||||
|
this.documentClickHandler = (event: MouseEvent) => {
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
// Check if click is outside any multiselect dropdown
|
||||||
|
if (!target.closest('.multiselect-container')) {
|
||||||
|
this.openMultiselects.clear();
|
||||||
|
this.removeDocumentClickHandler();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use setTimeout to ensure the click event that opened the dropdown doesn't immediately close it
|
||||||
|
setTimeout(() => {
|
||||||
|
document.addEventListener('click', this.documentClickHandler!);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove document click handler
|
||||||
|
private removeDocumentClickHandler(): void {
|
||||||
|
if (this.documentClickHandler) {
|
||||||
|
document.removeEventListener('click', this.documentClickHandler);
|
||||||
|
this.documentClickHandler = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if multiselect dropdown is open
|
||||||
|
isMultiselectOpen(filter: any, context: string): boolean {
|
||||||
|
const filterId = `${context}-${filter.field}`;
|
||||||
|
return this.openMultiselects.has(filterId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get count of selected options for a multiselect filter
|
||||||
|
getSelectedOptionsCount(filter: any): number {
|
||||||
|
if (!filter.value) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(filter.value)) {
|
||||||
|
return filter.value.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all filters
|
||||||
|
clearAllFilters(): void {
|
||||||
|
// Clear base filters
|
||||||
|
if (this.baseFilters) {
|
||||||
|
this.baseFilters.forEach(filter => {
|
||||||
|
if (filter.type === 'multiselect') {
|
||||||
|
filter.value = [];
|
||||||
|
} else if (filter.type === 'date-range') {
|
||||||
|
filter.value = { start: null, end: null };
|
||||||
|
} else if (filter.type === 'toggle') {
|
||||||
|
filter.value = false;
|
||||||
|
} else {
|
||||||
|
filter.value = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear drilldown filters
|
||||||
|
if (this.drilldownFilters) {
|
||||||
|
this.drilldownFilters.forEach(filter => {
|
||||||
|
if (filter.type === 'multiselect') {
|
||||||
|
filter.value = [];
|
||||||
|
} else if (filter.type === 'date-range') {
|
||||||
|
filter.value = { start: null, end: null };
|
||||||
|
} else if (filter.type === 'toggle') {
|
||||||
|
filter.value = false;
|
||||||
|
} else {
|
||||||
|
filter.value = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear layer filters
|
||||||
|
if (this.drilldownLayers) {
|
||||||
|
this.drilldownLayers.forEach(layer => {
|
||||||
|
if (layer.filters) {
|
||||||
|
layer.filters.forEach((filter: any) => {
|
||||||
|
if (filter.type === 'multiselect') {
|
||||||
|
filter.value = [];
|
||||||
|
} else if (filter.type === 'date-range') {
|
||||||
|
filter.value = { start: null, end: null };
|
||||||
|
} else if (filter.type === 'toggle') {
|
||||||
|
filter.value = false;
|
||||||
|
} else {
|
||||||
|
filter.value = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close all multiselect dropdowns
|
||||||
|
this.openMultiselects.clear();
|
||||||
|
|
||||||
|
// Refresh data
|
||||||
|
this.fetchChartData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user