From f740076d6066e7ef8bcb9193ea1cae579592782d Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Tue, 28 Oct 2025 17:04:02 +0530 Subject: [PATCH] bar chart --- .../bar-chart/bar-chart.component.html | 118 +++-- .../bar-chart/bar-chart.component.scss | 418 +++++++++++------- .../gadgets/bar-chart/bar-chart.component.ts | 61 ++- 3 files changed, 383 insertions(+), 214 deletions(-) diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.html index ff8a2cb..4c1ba64 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.html +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.html @@ -1,4 +1,4 @@ -
+
@@ -245,54 +245,90 @@
-
-
-

{{charttitle || 'Bar Chart'}}

+
+
+
+

{{charttitle || 'Bar Chart'}}

+
+
+ + +
-
- - -
-
- - -
-
-
-
-
-
- -
- - Drilldown Level: {{currentDrilldownLevel}} - - (Clicked on: {{drilldownStack[drilldownStack.length - 1].clickedLabel}}) + + +
+
+
+
+
+
+ +
+ + Drilldown Level: {{currentDrilldownLevel}} + + (Clicked on: {{drilldownStack[drilldownStack.length - 1].clickedLabel}}) + - +
- -
- No data available +
+
+ +
+ No data available +
+ + +
+ + +
+ +
+
+
+
- - -
- - + + + + + +
\ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.scss index a9282e4..c70fd33 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.scss +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.scss @@ -1,192 +1,278 @@ -.filter-section { - margin-bottom: 20px; - padding: 15px; - border: 1px solid #ddd; - border-radius: 4px; - background-color: #f9f9f9; -} - -.filter-group { - margin-bottom: 15px; - - h4 { - margin-top: 0; - margin-bottom: 10px; - color: #333; - font-weight: 600; - } -} - -.filter-controls { +// Chart container structure +.chart-container { + height: 100%; display: flex; - flex-wrap: wrap; - gap: 15px; -} - -.filter-item { - flex: 1 1 300px; - min-width: 250px; - padding: 10px; - background: white; - border: 1px solid #e0e0e0; - border-radius: 4px; -} - -.filter-label { - font-weight: 500; - margin-bottom: 8px; - color: #555; - font-size: 14px; -} - -.filter-input { - width: 100%; + flex-direction: column; - .filter-text-input, - .filter-select, - .filter-date { + // Filter section styling + .filter-section { + margin-bottom: 20px; + padding: 15px; + border: 1px solid #ddd; + border-radius: 4px; + background-color: #f9f9f9; + } + + .filter-group { + margin-bottom: 15px; + + h4 { + margin-top: 0; + margin-bottom: 10px; + color: #333; + font-weight: 600; + } + } + + .filter-controls { + display: flex; + flex-wrap: wrap; + gap: 15px; + } + + .filter-item { + flex: 1 1 300px; + min-width: 250px; + padding: 10px; + background: white; + border: 1px solid #e0e0e0; + border-radius: 4px; + } + + .filter-label { + font-weight: 500; + margin-bottom: 8px; + color: #555; + font-size: 14px; + } + + .filter-input { width: 100%; + + .filter-text-input, + .filter-select, + .filter-date { + width: 100%; + padding: 6px 12px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 14px; + } + + .filter-select { + height: 34px; + } + } + + .multiselect-container { + position: relative; + } + + .multiselect-display { + display: flex; + align-items: center; + justify-content: space-between; padding: 6px 12px; border: 1px solid #ccc; border-radius: 4px; - font-size: 14px; - } - - .filter-select { - height: 34px; - } -} - -.multiselect-container { - position: relative; -} - -.multiselect-display { - display: flex; - align-items: center; - justify-content: space-between; - padding: 6px 12px; - border: 1px solid #ccc; - border-radius: 4px; - background: white; - cursor: pointer; - min-height: 34px; - - .multiselect-label { - flex: 1; - font-size: 14px; - } - - .multiselect-value { - color: #666; - font-size: 12px; - margin-right: 8px; - } - - .dropdown-icon { - flex-shrink: 0; - transition: transform 0.2s ease; - } - - &:hover { - border-color: #999; - } -} - -.multiselect-dropdown { - position: absolute; - top: 100%; - left: 0; - right: 0; - z-index: 1000; - background: white; - border: 1px solid #ccc; - border-top: none; - border-radius: 0 0 4px 4px; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); - max-height: 200px; - overflow-y: auto; - - .checkbox-group { - padding: 8px; + background: white; + cursor: pointer; + min-height: 34px; - .checkbox-item { + .multiselect-label { + flex: 1; + font-size: 14px; + } + + .multiselect-value { + color: #666; + font-size: 12px; + margin-right: 8px; + } + + .dropdown-icon { + flex-shrink: 0; + transition: transform 0.2s ease; + } + + &:hover { + border-color: #999; + } + } + + .multiselect-dropdown { + position: absolute; + top: 100%; + left: 0; + right: 0; + z-index: 1000; + background: white; + border: 1px solid #ccc; + border-top: none; + border-radius: 0 0 4px 4px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + max-height: 200px; + overflow-y: auto; + + .checkbox-group { + padding: 8px; + + .checkbox-item { + display: flex; + align-items: center; + gap: 8px; + padding: 4px 0; + + .checkbox-label { + margin: 0; + font-size: 14px; + cursor: pointer; + } + } + } + } + + .date-range { + .date-input-group { display: flex; align-items: center; gap: 8px; - padding: 4px 0; + } + + .date-separator { + margin: 0 5px; + color: #777; + } + } + + .toggle { + display: flex; + align-items: center; + gap: 8px; + + .toggle-label { + margin: 0; + font-size: 14px; + cursor: pointer; + } + } + + .filter-actions { + margin-top: 15px; + padding-top: 15px; + border-top: 1px solid #eee; + + .btn { + font-size: 13px; + } + } + + // Chart header styling + .chart-header { + margin-bottom: 20px; + + .header-row { + margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; - .checkbox-label { + .chart-title { margin: 0; - font-size: 14px; - cursor: pointer; + font-size: 18px; + 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; + } } } } } -.date-range { - .date-input-group { - display: flex; - align-items: center; - gap: 8px; +@keyframes shimmer { + 0% { + background-position: -200% 0; } - - .date-separator { - margin: 0 5px; - color: #777; - } -} - -.toggle { - display: flex; - align-items: center; - gap: 8px; - - .toggle-label { - margin: 0; - font-size: 14px; - cursor: pointer; - } -} - -.filter-actions { - margin-top: 15px; - padding-top: 15px; - border-top: 1px solid #eee; - - .btn { - font-size: 13px; - } -} - -// New header row styling -.header-row { - margin-bottom: 15px; - padding-bottom: 10px; - border-bottom: 1px solid #eee; - - .chart-title { - margin: 0; - font-size: 18px; - font-weight: 600; - color: #333; + 100% { + background-position: 200% 0; } } // Responsive design @media (max-width: 768px) { - .filter-controls { - flex-direction: column; - } - - .filter-item { - min-width: 100%; - } - - .header-row { - .chart-title { - font-size: 16px; + .chart-container { + .filter-controls { + flex-direction: column; + } + + .filter-item { + min-width: 100%; + } + + .chart-header { + .header-row { + .chart-title { + font-size: 16px; + } + } + } + + .chart-content { + min-height: 250px; // Adjust for mobile } } } \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.ts index f8aed36..292f9ea 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.ts @@ -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)