bar chart

This commit is contained in:
string 2025-10-28 17:04:02 +05:30
parent bedcc0822d
commit f740076d60
3 changed files with 383 additions and 214 deletions

View File

@ -1,4 +1,4 @@
<div style="display: block; height: 100%; width: 100%;">
<div class="chart-container">
<!-- Filter Controls Section -->
<div class="filter-section" *ngIf="hasActiveFilters()">
<!-- Base Filters -->
@ -245,6 +245,7 @@
</div>
<!-- Header row with chart title and drilldown navigation -->
<div class="chart-header">
<div class="clr-row header-row">
<div class="clr-col-6">
<h3 class="chart-title">{{charttitle || 'Bar Chart'}}</h3>
@ -278,14 +279,17 @@
</div>
</div>
</div>
</div>
<!-- No data message -->
<div *ngIf="noDataAvailable" style="text-align: center; padding: 20px; color: #666; font-style: italic;">
<div class="chart-wrapper">
<div class="chart-content" [class.loading]="isLoading">
<div *ngIf="noDataAvailable" class="no-data-message">
No data available
</div>
<!-- Chart display -->
<div *ngIf="!noDataAvailable" style="position: relative; height: calc(100% - 50px);">
<div *ngIf="!noDataAvailable" class="chart-display">
<canvas baseChart
[datasets]="barChartData"
[labels]="barChartLabels"
@ -295,4 +299,36 @@
(chartClick)="chartClicked($event)">
</canvas>
</div>
<div class="loading-overlay" *ngIf="isLoading">
<div class="shimmer-bar"></div>
</div>
</div>
</div>
<!-- sheield dashboard -->
<!--
<div class="chart-container">
<div class="chart-header">
<h3>Deal Stage Wise Progress</h3>
</div>
<div class="chart-wrapper">
<div class="chart-content" [class.loading]="isLoading">
<canvas
baseChart
[data]="barChartData"
[options]="barChartOptions"
[type]="barChartType"
(chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)">
</canvas>
<div class="loading-overlay" *ngIf="isLoading">
<div class="shimmer-bar"></div>
</div>
</div>
</div>
</div> -->
</div>

View File

@ -1,12 +1,19 @@
.filter-section {
// Chart container structure
.chart-container {
height: 100%;
display: flex;
flex-direction: column;
// Filter section styling
.filter-section {
margin-bottom: 20px;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f9f9f9;
}
}
.filter-group {
.filter-group {
margin-bottom: 15px;
h4 {
@ -15,31 +22,31 @@
color: #333;
font-weight: 600;
}
}
}
.filter-controls {
.filter-controls {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
}
.filter-item {
.filter-item {
flex: 1 1 300px;
min-width: 250px;
padding: 10px;
background: white;
border: 1px solid #e0e0e0;
border-radius: 4px;
}
}
.filter-label {
.filter-label {
font-weight: 500;
margin-bottom: 8px;
color: #555;
font-size: 14px;
}
}
.filter-input {
.filter-input {
width: 100%;
.filter-text-input,
@ -55,13 +62,13 @@
.filter-select {
height: 34px;
}
}
}
.multiselect-container {
.multiselect-container {
position: relative;
}
}
.multiselect-display {
.multiselect-display {
display: flex;
align-items: center;
justify-content: space-between;
@ -91,9 +98,9 @@
&:hover {
border-color: #999;
}
}
}
.multiselect-dropdown {
.multiselect-dropdown {
position: absolute;
top: 100%;
left: 0;
@ -123,9 +130,9 @@
}
}
}
}
}
.date-range {
.date-range {
.date-input-group {
display: flex;
align-items: center;
@ -136,9 +143,9 @@
margin: 0 5px;
color: #777;
}
}
}
.toggle {
.toggle {
display: flex;
align-items: center;
gap: 8px;
@ -148,9 +155,9 @@
font-size: 14px;
cursor: pointer;
}
}
}
.filter-actions {
.filter-actions {
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #eee;
@ -158,10 +165,13 @@
.btn {
font-size: 13px;
}
}
}
// New header row styling
.header-row {
// Chart header styling
.chart-header {
margin-bottom: 20px;
.header-row {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
@ -172,10 +182,79 @@
font-weight: 600;
color: #333;
}
}
}
// Chart wrapper and content
.chart-wrapper {
flex: 1;
position: relative;
.chart-content {
position: relative;
height: 100%;
min-height: 300px; // Ensure minimum height for chart
&.loading {
opacity: 0.7;
.chart-display {
filter: blur(2px);
}
}
.no-data-message {
text-align: center;
padding: 20px;
color: #666;
font-style: italic;
}
.chart-display {
position: relative;
height: 100%;
width: 100%;
max-width: 100%;
max-height: 100%;
transition: filter 0.3s ease;
}
.loading-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.8);
.shimmer-bar {
width: 80%;
height: 20px;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 4px;
}
}
}
}
}
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
// Responsive design
@media (max-width: 768px) {
.chart-container {
.filter-controls {
flex-direction: column;
}
@ -184,9 +263,16 @@
min-width: 100%;
}
.chart-header {
.header-row {
.chart-title {
font-size: 16px;
}
}
}
.chart-content {
min-height: 250px; // Adjust for mobile
}
}
}

View File

@ -57,21 +57,46 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
ticks: {
autoSkip: false,
maxRotation: 45,
minRotation: 45
minRotation: 45,
padding: 15,
font: {
size: 12
}
},
grid: {
display: false
}
},
y: {
beginAtZero: true
beginAtZero: true,
ticks: {
font: {
size: 12
}
}
}
},
plugins: {
legend: {
display: true,
position: 'top',
labels: {
font: {
size: 12
}
}
},
tooltip: {
enabled: true
}
},
layout: {
padding: {
bottom: 60,
left: 15,
right: 15,
top: 15
}
}
};
@ -84,6 +109,9 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
// No data state
noDataAvailable: boolean = false;
// Loading state
isLoading: boolean = false;
// Flag to prevent infinite loops
private isFetchingData: boolean = false;
@ -463,14 +491,18 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
}
fetchChartData(): void {
// Set loading state
this.isLoading = true;
// Set flag to prevent recursive calls
this.isFetchingData = true;
// If we're in drilldown mode, fetch the appropriate drilldown data
if (this.currentDrilldownLevel > 0 && this.drilldownStack.length > 0) {
this.fetchDrilldownData();
// Reset flag after fetching
// Reset flags after fetching
this.isFetchingData = false;
this.isLoading = false;
return;
}
@ -540,8 +572,9 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
this.noDataAvailable = true;
this.barChartLabels = [];
this.barChartData = [];
// Reset flag after fetching
// Reset flags after fetching
this.isFetchingData = false;
this.isLoading = false;
return;
}
@ -570,8 +603,9 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
this.barChartLabels = [];
this.barChartData = [];
}
// Reset flag after fetching
// Reset flags after fetching
this.isFetchingData = false;
this.isLoading = false;
},
(error) => {
console.error('=== BAR CHART ERROR ===');
@ -579,8 +613,9 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
this.noDataAvailable = true;
this.barChartLabels = [];
this.barChartData = [];
// Reset flag after fetching
// Reset flags after fetching
this.isFetchingData = false;
this.isLoading = false;
// Keep default data in case of error
}
);
@ -592,8 +627,9 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
this.noDataAvailable = true;
this.barChartLabels = [];
this.barChartData = [];
// Reset flag after fetching
// Reset flags after fetching
this.isFetchingData = false;
this.isLoading = false;
}
}
@ -755,17 +791,23 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
// Trigger change detection
// this.barChartData = [...this.barChartData];
console.log('Updated bar chart with drilldown data:', { labels: this.barChartLabels, data: this.barChartData });
// Set loading state to false
this.isLoading = false;
} else if (data && data.labels && data.datasets) {
// Backend has already filtered the data, just display it
this.noDataAvailable = data.labels.length === 0;
this.barChartLabels = data.labels;
this.barChartData = data.datasets;
console.log('Updated bar chart with drilldown legacy data format:', { labels: this.barChartLabels, data: this.barChartData });
// Set loading state to false
this.isLoading = false;
} else {
console.warn('Drilldown received data does not have expected structure', data);
this.noDataAvailable = true;
this.barChartLabels = [];
this.barChartData = [];
// Set loading state to false
this.isLoading = false;
}
},
(error) => {
@ -773,12 +815,17 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy {
this.noDataAvailable = true;
this.barChartLabels = [];
this.barChartData = [];
// Set loading state to false
this.isLoading = false;
// Keep current data in case of error
}
);
// Add subscription to array for cleanup
this.subscriptions.push(subscription);
// Set loading state
this.isLoading = true;
}
// Reset to original data (go back to base level)