diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/common-filter/compact-filter.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/common-filter/compact-filter.component.scss index 6f044c4..ee880b3 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/common-filter/compact-filter.component.scss +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/common-filter/compact-filter.component.scss @@ -70,6 +70,41 @@ min-height: 24px; } + .multiselect-container { + max-height: 150px; + overflow-y: auto; + border: 1px solid #ddd; + border-radius: 4px; + padding: 5px; + background: white; + } + + .checkbox-group { + display: flex; + flex-direction: column; + gap: 3px; + } + + .checkbox-item { + display: flex; + align-items: center; + gap: 5px; + } + + .checkbox-label { + font-size: 12px; + margin: 0; + cursor: pointer; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .clr-checkbox { + margin: 0; + cursor: pointer; + } + .toggle-label { margin: 0; font-size: 12px; diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/common-filter/compact-filter.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/common-filter/compact-filter.component.ts index 90d5bcf..7424e96 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/common-filter/compact-filter.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/common-filter/compact-filter.component.ts @@ -38,19 +38,6 @@ export class CompactFilterComponent implements OnInit, OnChanges { ) { } ngOnInit(): void { - // Subscribe to filter definitions to get available filters - this.filterService.filters$.subscribe(filters => { - this.availableFilters = filters; - this.updateSelectedFilter(); - }); - - // Subscribe to filter state changes - this.filterService.filterState$.subscribe(state => { - if (this.selectedFilter && state.hasOwnProperty(this.selectedFilter.id)) { - this.filterValue = state[this.selectedFilter.id]; - } - }); - // Initialize configuration from inputs this.configFilterKey = this.filterKey; this.configFilterType = this.filterType; @@ -70,26 +57,53 @@ export class CompactFilterComponent implements OnInit, OnChanges { // Register this filter with the filter service this.registerFilter(); + + // Subscribe to filter definitions to get available filters + this.filterService.filters$.subscribe(filters => { + this.availableFilters = filters; + this.updateSelectedFilter(); + }); + + // Subscribe to filter state changes + this.filterService.filterState$.subscribe(state => { + if (this.selectedFilter && state.hasOwnProperty(this.selectedFilter.id)) { + this.filterValue = state[this.selectedFilter.id]; + } + }); } ngOnChanges(changes: SimpleChanges): void { // If filterKey or filterType changes, re-register the filter if (changes.filterKey || changes.filterType) { + // Load available values for the current filter key if it's a dropdown or multiselect + if ((this.filterType === 'dropdown' || this.filterType === 'multiselect') && this.filterKey) { + this.loadAvailableValues(this.filterKey); + } this.registerFilter(); } + + // Handle API URL changes + if (changes.apiUrl && !changes.apiUrl.firstChange) { + if (this.apiUrl) { + this.loadAvailableKeys(); + } + } } // Register this filter with the filter service registerFilter(): void { if (this.filterKey) { + // Get current filter values from the service + const currentFilterValues = this.filterService.getFilterValues(); + // Create a filter definition for this compact filter const filterDef: Filter = { - id: `compact-filter-${this.filterKey}`, + id: `${this.filterKey}`, field: this.filterKey, label: this.filterLabel || this.filterKey, type: this.filterType as any, options: this.filterOptions, - value: this.filterValue + value: this.filterValue // Use the current filter value }; // Get current filters @@ -99,9 +113,32 @@ export class CompactFilterComponent implements OnInit, OnChanges { const existingFilterIndex = currentFilters.findIndex(f => f.id === filterDef.id); if (existingFilterIndex >= 0) { + // Preserve the existing filter configuration + const existingFilter = currentFilters[existingFilterIndex]; + + // Preserve the existing filter value if it exists in the service + if (currentFilterValues.hasOwnProperty(existingFilter.id)) { + filterDef.value = currentFilterValues[existingFilter.id]; + this.filterValue = filterDef.value; // Update local value + } else if (existingFilter.value !== undefined) { + // Fallback to existing filter's value if no service value + filterDef.value = existingFilter.value; + this.filterValue = filterDef.value; + } + + // Preserve other configuration properties + filterDef.label = existingFilter.label; + filterDef.options = existingFilter.options || this.filterOptions; + // Update existing filter currentFilters[existingFilterIndex] = filterDef; } else { + // For new filters, check if there's already a value in the service + if (currentFilterValues.hasOwnProperty(filterDef.id)) { + filterDef.value = currentFilterValues[filterDef.id]; + this.filterValue = filterDef.value; // Update local value + } + // Add new filter currentFilters.push(filterDef); } @@ -118,9 +155,24 @@ export class CompactFilterComponent implements OnInit, OnChanges { if (this.filterKey && this.availableFilters.length > 0) { this.selectedFilter = this.availableFilters.find(f => f.field === this.filterKey) || null; if (this.selectedFilter) { - // Get current value for this filter + // Get current value for this filter from the service const currentState = this.filterService.getFilterValues(); - this.filterValue = currentState[this.selectedFilter.id] || ''; + const filterValue = currentState[this.selectedFilter.id]; + if (filterValue !== undefined) { + this.filterValue = filterValue; + } else if (this.selectedFilter.value !== undefined) { + // Use the filter's default value if no service value + this.filterValue = this.selectedFilter.value; + } else { + // Use the current filter value as fallback + this.filterValue = this.filterValue || ''; + } + + // Also update configuration properties from the selected filter + this.configFilterKey = this.selectedFilter.field; + this.configFilterType = this.selectedFilter.type; + this.configFilterLabel = this.selectedFilter.label; + this.configFilterOptions = (this.selectedFilter.options || []).join(','); } } } @@ -130,6 +182,14 @@ export class CompactFilterComponent implements OnInit, OnChanges { this.filterValue = value; this.filterService.updateFilterValue(this.selectedFilter.id, value); this.filterChange.emit({ filterId: this.selectedFilter.id, value: value }); + + // Update the filter definition in the service to reflect the new value + const currentFilters = this.filterService.getFilters(); + const filterIndex = currentFilters.findIndex(f => f.id === this.selectedFilter.id); + if (filterIndex >= 0) { + currentFilters[filterIndex].value = value; + this.filterService.setFilters(currentFilters); + } } } @@ -179,11 +239,19 @@ export class CompactFilterComponent implements OnInit, OnChanges { toggleConfigMode(): void { this.isConfigMode = !this.isConfigMode; if (this.isConfigMode) { - // Initialize config values - this.configFilterKey = this.filterKey; - this.configFilterType = this.filterType; - this.configFilterLabel = this.filterLabel; - this.configFilterOptions = this.filterOptions.join(','); + // Initialize config values from current filter if available + if (this.selectedFilter) { + this.configFilterKey = this.selectedFilter.field; + this.configFilterType = this.selectedFilter.type; + this.configFilterLabel = this.selectedFilter.label; + this.configFilterOptions = (this.selectedFilter.options || []).join(','); + } else { + // Fallback to current properties + this.configFilterKey = this.filterKey; + this.configFilterType = this.filterType; + this.configFilterLabel = this.filterLabel; + this.configFilterOptions = this.filterOptions.join(','); + } this.configApiUrl = this.apiUrl; this.configConnectionId = this.connectionId; } @@ -216,8 +284,8 @@ export class CompactFilterComponent implements OnInit, OnChanges { } // Load available values for the selected key if it's a dropdown or multiselect - if ((this.filterType === 'dropdown' || this.filterType === 'multiselect') && this.filterKey) { - this.loadAvailableValues(this.filterKey); + if ((this.configFilterType === 'dropdown' || this.configFilterType === 'multiselect') && this.configFilterKey) { + this.loadAvailableValues(this.configFilterKey); } // Register the updated filter with the filter service diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.html index a440ffc..f5613c8 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.html +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.html @@ -550,6 +550,95 @@ --> + + +
+
+

Compact Filter Configuration

+ +
+
+ + +
Select a connection for this compact filter
+
+
+ +
+
+ +
+ + + + +
+
Enter the API URL to fetch data for this filter
+
+
+ +
+
+ + +
Select the field name to filter on
+
+
+ +
+
+ + +
Select the type of filter control to display
+
+
+ +
+
+ + +
Label to display for this filter in the UI (if not provided, filter key will be used)
+
+
+ +
+
+ + +
Comma-separated list of options for dropdown/multiselect filters
+
+ Available values for "{{ gadgetsEditdata.filterKey }}": {{ filterOptionsString }} +
+
+
+
+
+ diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/dashrunnerline.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/dashrunnerline.component.ts index 61f9a3c..ea34202 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/dashrunnerline.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/dashrunnerline.component.ts @@ -17,6 +17,10 @@ import { BubbleRunnerComponent } from './bubble-runner/bubble-runner.component'; import { ScatterRunnerComponent } from './scatter-runner/scatter-runner.component'; import { PolarRunnerComponent } from './polar-runner/polar-runner.component'; import { RadarRunnerComponent } from './radar-runner/radar-runner.component'; +// Add FilterService import +import { FilterService } from '../../dashboardnew/common-filter/filter.service'; +// Add CompactFilterRunnerComponent import +import { CompactFilterRunnerComponent } from './compact-filter-runner/compact-filter-runner.component'; @Component({ selector: 'app-dashrunnerline', @@ -44,10 +48,13 @@ export class DashrunnerlineComponent implements OnInit { { name: "Radar Chart", componentInstance: RadarRunnerComponent }, { name: "Grid View", componentInstance: GridRunnerComponent }, { name: "To Do Chart", componentInstance: TodoRunnerComponent }, + { name: "Compact Filter", componentInstance: CompactFilterRunnerComponent }, // Add Compact Filter Runner ]; constructor(private Dashtestservive:DashrunnerService, private dashboardService: Dashboard3Service,private route: ActivatedRoute, - private router : Router,) { } + private router : Router, + // Add FilterService to constructor + private filterService: FilterService) { } ngOnInit(): void { @@ -288,4 +295,48 @@ dashboard_name = "Dashtest"; console.log('Button clicked in SomeComponent'); // Add your custom logic here when the button is clicked in SomeComponent } + + // Method to provide inputs for dynamic components based on their type + getComponentInputs(item: any): any { + const inputs: any = {}; + + // Common inputs for all components + if (item.table !== undefined) inputs.table = item.table; + if (item.xAxis !== undefined) inputs.xAxis = item.xAxis; + if (item.yAxis !== undefined) inputs.yAxis = item.yAxis; + if (item.connection !== undefined) inputs.connection = item.connection; + if (item.charttitle !== undefined) inputs.charttitle = item.charttitle; + if (item.chartlegend !== undefined) inputs.chartlegend = item.chartlegend; + if (item.showlabel !== undefined) inputs.showlabel = item.showlabel; + + // Compact Filter specific inputs + if (item.name === 'Compact Filter') { + if (item.filterKey !== undefined) inputs.filterKey = item.filterKey; + if (item.filterType !== undefined) inputs.filterType = item.filterType; + if (item.filterLabel !== undefined) inputs.filterLabel = item.filterLabel; + if (item.filterOptions !== undefined) inputs.filterOptions = item.filterOptions; + if (item.table !== undefined) inputs.apiUrl = item.table; // Use table as API URL for compact filter + if (item.connection !== undefined) inputs.connection = item.connection ? parseInt(item.connection, 10) : undefined; + } + + // Grid View specific inputs + if (item.name === 'Grid View') { + if (item.baseFilters !== undefined) inputs.baseFilters = item.baseFilters; + } + + // Chart specific inputs + if (item.name.includes('Chart') && item.name !== 'Compact Filter') { + if (item.baseFilters !== undefined) inputs.baseFilters = item.baseFilters; + if (item.drilldownEnabled !== undefined) inputs.drilldownEnabled = item.drilldownEnabled; + if (item.drilldownApiUrl !== undefined) inputs.drilldownApiUrl = item.drilldownApiUrl; + if (item.drilldownXAxis !== undefined) inputs.drilldownXAxis = item.drilldownXAxis; + if (item.drilldownYAxis !== undefined) inputs.drilldownYAxis = item.drilldownYAxis; + if (item.drilldownParameter !== undefined) inputs.drilldownParameter = item.drilldownParameter; + if (item.drilldownFilters !== undefined) inputs.drilldownFilters = item.drilldownFilters; + if (item.drilldownLayers !== undefined) inputs.drilldownLayers = item.drilldownLayers; + } + + console.log('Component inputs for', item.name, ':', inputs); + return inputs; + } } diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/doughnut-runner/doughnut-runner.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/doughnut-runner/doughnut-runner.component.ts index f92400c..700d621 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/doughnut-runner/doughnut-runner.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/doughnut-runner/doughnut-runner.component.ts @@ -5,6 +5,10 @@ import { ChartDataset, ChartType, } from 'chart.js'; import { ActivatedRoute, Router } from '@angular/router'; import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; import { DashboardContentModel } from 'src/app/models/builder/dashboard'; +// Add FilterService import +import { FilterService } from '../../../dashboardnew/common-filter/filter.service'; +// Add Subscription import +import { Subscription } from 'rxjs'; @Component({ selector: 'app-doughnut-runner', @@ -33,10 +37,16 @@ export class DoughnutRunnerComponent implements OnInit { "chartLabels": ["Project", "Repository", "Wireframe"] } doughnutChartType: ChartType = 'doughnut'; + ConnectionId: number; // Add ConnectionId property + + // Add subscriptions to unsubscribe on destroy + private subscriptions: Subscription[] = []; constructor(private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, - private router : Router,) { } + private router : Router, + // Add FilterService to constructor + private filterService: FilterService) { } ngOnInit(): void { this.doughnutChartData = this.doughnutData.chartData; this.doughnutChartLabels = this.doughnutData.chartLabels; @@ -44,6 +54,14 @@ export class DoughnutRunnerComponent implements OnInit { this.editId = this.route.snapshot.params.id; console.log(this.editId); + // Subscribe to filter changes + this.subscriptions.push( + this.filterService.filterState$.subscribe(filters => { + // When filters change, refresh the chart data + this.fetchChartData(); + }) + ); + this.dashboardService.getById(this.editId).subscribe((data)=>{ console.log(data); this.workflowLine = data.dashbord1_Line[0].model; @@ -70,22 +88,62 @@ export class DoughnutRunnerComponent implements OnInit { this.YAxis = ChartObject[i].yAxis; this.showlabel = ChartObject[i].showlabel; this.doughnutChartLegend = ChartObject[i].chartlegend; + this.ConnectionId = ChartObject[i].connection; // Add connection ID console.log(this.TableName); - this.Dashtestservive.getChartData(this.TableName,"Doughnut Chart",this.XAxis,this.YAxis).subscribe((Ldata) => { - console.log(Ldata); - this.JsonData = Ldata; - this.doughnutChartData = this.JsonData.chartData; - this.doughnutChartLabels = this.JsonData.chartLabels; - - },(error) => { - console.log(error); - }); + // Fetch data with filters + this.fetchChartData(); break; // No need to continue the loop once the correct placeholder is found } } }); } - + + // Fetch chart data with filter support + fetchChartData(): void { + if (this.TableName && this.XAxis && this.YAxis) { + // Convert YAxis to string if it's an array + const yAxisString = Array.isArray(this.YAxis) ? this.YAxis.join(',') : this.YAxis; + + // Get filter parameters from common filters + const commonFilters = this.filterService.getFilterValues(); + const filterDefinitions = this.filterService.getFilters(); + + // Build filter object using field names as keys + const filterObj = {}; + Object.keys(commonFilters).forEach(filterId => { + const filterValue = commonFilters[filterId]; + + // Find the filter definition to get the field name + const filterDef = this.filterService.getFilters().find(f => f.id === filterId); + + if (filterDef && filterDef.field) { + const fieldName = filterDef.field; + if (filterValue !== undefined && filterValue !== null && filterValue !== '') { + filterObj[fieldName] = filterValue; + } + } + }); + + // Convert to JSON string for API call + let filterParams = ''; + if (Object.keys(filterObj).length > 0) { + filterParams = JSON.stringify(filterObj); + } + + console.log('DoughnutRunner: Final filter object to send to API:', filterObj); + + // Fetch data from the dashboard service with filters + this.Dashtestservive.getChartDataWithFilters(this.TableName, "Doughnut Chart", this.XAxis, this.YAxis, this.ConnectionId, '', '', filterParams).subscribe((Ldata) => { + console.log(Ldata); + this.JsonData = Ldata; + this.doughnutChartData = this.JsonData.chartData; + this.doughnutChartLabels = this.JsonData.chartLabels; + },(error) => { + console.log(error); + }); + } + } + generatePDFFile(){ // this.buttonClicked.emit(); const content = this.contentContainerRef.nativeElement; @@ -93,6 +151,19 @@ export class DoughnutRunnerComponent implements OnInit { this.Dashtestservive.generatePDF(content, filename); } + + ngOnDestroy() { + // Unsubscribe from all subscriptions to prevent memory leaks + console.log('DoughnutRunnerComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions'); + this.subscriptions.forEach(subscription => { + if (subscription && !subscription.closed) { + subscription.unsubscribe(); + } + }); + this.subscriptions = []; + + console.log('DoughnutRunnerComponent destroyed and cleaned up'); + } diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/grid-runner/grid-runner.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/grid-runner/grid-runner.component.html index 4761acc..9b55a47 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/grid-runner/grid-runner.component.html +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/grid-runner/grid-runner.component.html @@ -39,16 +39,35 @@ -->
- + +
+

Debug Information

+

TableName: {{ TableName }}

+

XAxis: {{ XAxis }}

+

YAxis: {{ YAxis }}

+

Rows: {{ rows?.length }} items

+

Headers: {{ getHeaders() | json }}

+
Error: {{ error }}
+
+ +
+ {{ error }} +
+ +
- +
{{co}}
{{item[key]}}
+ + +

No data available

+
\ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/grid-runner/grid-runner.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/grid-runner/grid-runner.component.ts index 9e1f6ac..c71474d 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/grid-runner/grid-runner.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/grid-runner/grid-runner.component.ts @@ -3,6 +3,10 @@ import { DashrunnerService } from '../dashrunner.service'; import { DashboardContentModel } from 'src/app/models/builder/dashboard'; import { ActivatedRoute, Router } from '@angular/router'; import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; +// Add FilterService import +import { FilterService } from '../../../dashboardnew/common-filter/filter.service'; +// Add Subscription import +import { Subscription } from 'rxjs'; @Component({ selector: 'app-grid-runner', @@ -26,86 +30,191 @@ export class GridRunnerComponent implements OnInit { public DashtestboardArray: DashboardContentModel[] = []; workflowLine; TableName; + ConnectionId: number; // Add ConnectionId property + + // Add subscriptions to unsubscribe on destroy + private subscriptions: Subscription[] = []; constructor( - private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, - private router : Router + private Dashtestservive:DashrunnerService, + private route: ActivatedRoute, + private dashboardService: Dashboard3Service, + private router : Router, + // Add FilterService to constructor + private filterService: FilterService ) { } ngOnInit(): void { this.editId = this.route.snapshot.params.id; - console.log(this.editId); + console.log('GridRunner: Component initialized with editId:', this.editId); // this.getbyId(); - this.dashboardService.getById(this.editId).subscribe((data)=>{ - console.log(data); + // Subscribe to filter changes + this.subscriptions.push( + this.filterService.filterState$.subscribe(filters => { + console.log('GridRunner: Filter state changed:', filters); + // When filters change, refresh the grid data + this.fetchGridData(); + }) + ); + + this.dashboardService.getById(this.editId).subscribe((data) => { + console.log('GridRunner: Received dashboard data:', data); this.workflowLine = data.dashbord1_Line[0].model; - const dash = JSON.parse(this.workflowLine) ; + const dash = JSON.parse(this.workflowLine); // this.DashtestboardArray = dash.dashboard; // console.log(this.DashtestboardArray); const ChartObject = dash.dashboard.filter(obj => obj.name === "Grid View"); - console.log(ChartObject); + console.log('GridRunner: ChartObject for Grid View:', ChartObject); for (let i = 0; i < ChartObject.length; i++) { const ids = this.Dashtestservive.getgridview(); + console.log('GridRunner: Current gridview ids:', ids); + console.log('GridRunner: Checking chartid:', ChartObject[i].chartid); // console.log(ids); if (ids.includes(ChartObject[i].chartid)) { // If the chartid is already in the ids array, continue to the next iteration + console.log('GridRunner: Skipping chartid as it already exists:', ChartObject[i].chartid); continue; } + console.log('GridRunner: Adding new chartid:', ChartObject[i].chartid); this.Dashtestservive.setgridview(ChartObject[i].chartid); - const id = ids[i]; - console.log(id); - - if (ChartObject[i].chartid === id) { - this.TableName = ChartObject[i].table; - this.XAxis = ChartObject[i].xAxis; - this.YAxis = ChartObject[i].yAxis; - console.log(this.TableName); - this.Dashtestservive.getChartData(this.TableName,"Grid View",this.XAxis,this.YAxis).subscribe((Ldata) => { - console.log(Ldata); - this.rows = Ldata; - this.rowdata = this.rows - - },(error) => { - console.log(error); - }); - break; // No need to continue the loop once the correct placeholder is found - } + + this.TableName = ChartObject[i].table; + this.XAxis = ChartObject[i].xAxis; + this.YAxis = ChartObject[i].yAxis; + // Add connection ID if available + this.ConnectionId = ChartObject[i].connection; + console.log('GridRunner: TableName:', this.TableName); + console.log('GridRunner: XAxis:', this.XAxis); + console.log('GridRunner: YAxis:', this.YAxis); + console.log('GridRunner: ConnectionId:', this.ConnectionId); + // Fetch data with filters + this.fetchGridData(); + break; // No need to continue the loop once the correct placeholder is found } + }, (error) => { + console.log('GridRunner: Error fetching dashboard data:', error); }); } + // Fetch grid data with filter support + fetchGridData(): void { + console.log('fetching grid data ...') + if (this.TableName) { + console.log('GridRunner: Fetching data for TableName:', this.TableName, 'XAxis:', this.XAxis, 'YAxis:', this.YAxis); + // Convert YAxis to string if it's an array + const yAxisString = Array.isArray(this.YAxis) ? this.YAxis.join(',') : this.YAxis; - -//dynamic table + // Get filter parameters from common filters + const commonFilters = this.filterService.getFilterValues(); + const filterDefinitions = this.filterService.getFilters(); + // Build filter object using field names as keys + const filterObj = {}; + Object.keys(commonFilters).forEach(filterId => { + const filterValue = commonFilters[filterId]; -getTableData(id){ -} -getHeaders() { -let headers: string[] = []; -if(this.rows) { - this.rows.forEach((value) => { - Object.keys(value).forEach((key) => { - if(!headers.find((header) => header == key)){ - headers.push(key) + // Find the filter definition to get the field name + const filterDef = this.filterService.getFilters().find(f => f.id === filterId); + + if (filterDef && filterDef.field) { + const fieldName = filterDef.field; + if (filterValue !== undefined && filterValue !== null && filterValue !== '') { + filterObj[fieldName] = filterValue; + } + } + }); + + // Convert to JSON string for API call + let filterParams = ''; + if (Object.keys(filterObj).length > 0) { + filterParams = JSON.stringify(filterObj); } - }) + console.log('GridRunner: Final filter object to send to API:', filterObj); - }) -} -return headers; -} + // Fetch data from the dashboard service with filters + this.Dashtestservive.getChartDataWithFilters(this.TableName, "grid", this.XAxis, this.YAxis, this.ConnectionId, '', '', filterParams).subscribe((Ldata) => { + console.log('GridRunner: Received data from API:', Ldata); -generatePDFFile(){ - this.buttonClicked.emit(); - const content = this.contentContainerRef.nativeElement; - const filename = 'gridview.pdf'; // You can provide any desired filename here + // Handle the actual data structure returned by the API + if (Ldata && Ldata.chartData) { + this.rows = Ldata.chartData; + this.rowdata = this.rows; + } else if (Ldata && Ldata.data) { + // Handle the original expected format as fallback + this.rows = Ldata.data; + this.rowdata = this.rows; + } else if (Array.isArray(Ldata)) { + // Handle case where data is directly an array + this.rows = Ldata; + this.rowdata = this.rows; + } else { + console.warn('GridRunner: Received data does not have expected structure', Ldata); + this.rows = []; + this.rowdata = []; + } - this.Dashtestservive.generatePDF(content, filename); -} -} + // Log the structure of the received data + if (this.rows) { + console.log('GridRunner: Rows length:', this.rows.length); + if (this.rows.length > 0) { + console.log('GridRunner: First row structure:', this.rows[0]); + } + } else { + console.log('GridRunner: No data received'); + } + }, (error) => { + console.log('GridRunner: Error fetching data:', error); + this.error = error; + }); + } else { + console.log('GridRunner: Missing TableName or XAxis'); + } + } + + //dynamic table + + + getTableData(id) { + } + getHeaders() { + let headers: string[] = []; + if (this.rows) { + console.log('GridRunner: Getting headers from rows:', this.rows); + this.rows.forEach((value) => { + Object.keys(value).forEach((key) => { + if (!headers.find((header) => header == key)) { + headers.push(key) + } + }) + }) + } + console.log('GridRunner: Computed headers:', headers); + return headers; + } + + generatePDFFile() { + this.buttonClicked.emit(); + const content = this.contentContainerRef.nativeElement; + const filename = 'gridview.pdf'; // You can provide any desired filename here + + this.Dashtestservive.generatePDF(content, filename); + } + + ngOnDestroy() { + // Unsubscribe from all subscriptions to prevent memory leaks + console.log('GridRunnerComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions'); + this.subscriptions.forEach(subscription => { + if (subscription && !subscription.closed) { + subscription.unsubscribe(); + } + }); + this.subscriptions = []; + + console.log('GridRunnerComponent destroyed and cleaned up'); + } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/line-runner/line-runner.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/line-runner/line-runner.component.ts index 93d621b..c815f4b 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/line-runner/line-runner.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/line-runner/line-runner.component.ts @@ -7,6 +7,10 @@ import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; import { DashboardContentModel } from 'src/app/models/builder/dashboard'; import { jsPDF } from 'jspdf'; import domtoimage from 'dom-to-image'; +// Add FilterService import +import { FilterService } from '../../../dashboardnew/common-filter/filter.service'; +// Add Subscription import +import { Subscription } from 'rxjs'; @Component({ selector: 'app-line-runner', templateUrl: './line-runner.component.html', @@ -54,8 +58,14 @@ export class LineRunnerComponent implements OnInit { lineChartLegend = false; lineChartPlugins = []; lineChartType = 'line'; + ConnectionId: number; // Add ConnectionId property + + // Add subscriptions to unsubscribe on destroy + private subscriptions: Subscription[] = []; constructor(private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, - private router : Router,) { } + private router : Router, + // Add FilterService to constructor + private filterService: FilterService) { } ngOnInit(): void { @@ -65,6 +75,13 @@ export class LineRunnerComponent implements OnInit { this.editId = this.route.snapshot.params.id; console.log(this.editId); + // Subscribe to filter changes + this.subscriptions.push( + this.filterService.filterState$.subscribe(filters => { + // When filters change, refresh the chart data + this.fetchChartData(); + }) + ); this.dashboardService.getById(this.editId).subscribe((data)=>{ console.log(data); @@ -92,16 +109,10 @@ export class LineRunnerComponent implements OnInit { this.YAxis = ChartObject[i].yAxis; this.showlabel = ChartObject[i].showlabel; this.lineChartLegend = ChartObject[i].chartlegend; + this.ConnectionId = ChartObject[i].connection; // Add connection ID console.log(this.TableName); - this.Dashtestservive.getChartData(this.TableName,"Line Chart",this.XAxis,this.YAxis).subscribe((Ldata) => { - console.log(Ldata); - this.JsonData = Ldata; - this.lineChartData = this.JsonData.chartData; - this.lineChartLabels = this.JsonData.chartLabels; - - },(error) => { - console.log(error); - }); + // Fetch data with filters + this.fetchChartData(); break; // No need to continue the loop once the correct placeholder is found } } @@ -128,6 +139,52 @@ export class LineRunnerComponent implements OnInit { // } } + // Fetch chart data with filter support + fetchChartData(): void { + if (this.TableName && this.XAxis && this.YAxis) { + // Convert YAxis to string if it's an array + const yAxisString = Array.isArray(this.YAxis) ? this.YAxis.join(',') : this.YAxis; + + // Get filter parameters from common filters + const commonFilters = this.filterService.getFilterValues(); + const filterDefinitions = this.filterService.getFilters(); + + // Build filter object using field names as keys + const filterObj = {}; + Object.keys(commonFilters).forEach(filterId => { + const filterValue = commonFilters[filterId]; + + // Find the filter definition to get the field name + const filterDef = this.filterService.getFilters().find(f => f.id === filterId); + + if (filterDef && filterDef.field) { + const fieldName = filterDef.field; + if (filterValue !== undefined && filterValue !== null && filterValue !== '') { + filterObj[fieldName] = filterValue; + } + } + }); + + // Convert to JSON string for API call + let filterParams = ''; + if (Object.keys(filterObj).length > 0) { + filterParams = JSON.stringify(filterObj); + } + + console.log('LineRunner: Final filter object to send to API:', filterObj); + + // Fetch data from the dashboard service with filters + this.Dashtestservive.getChartDataWithFilters(this.TableName, "Line Chart", this.XAxis, this.YAxis, this.ConnectionId, '', '', filterParams).subscribe((Ldata) => { + console.log(Ldata); + this.JsonData = Ldata; + this.lineChartData = this.JsonData.chartData; + this.lineChartLabels = this.JsonData.chartLabels; + },(error) => { + console.log(error); + }); + } + } + generatePDFFile(){ this.buttonClicked.emit(); const content = this.contentContainerRef.nativeElement; @@ -165,5 +222,18 @@ export class LineRunnerComponent implements OnInit { // console.error('Error generating PDF:', error); // } // } + + ngOnDestroy() { + // Unsubscribe from all subscriptions to prevent memory leaks + console.log('LineRunnerComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions'); + this.subscriptions.forEach(subscription => { + if (subscription && !subscription.closed) { + subscription.unsubscribe(); + } + }); + this.subscriptions = []; + + console.log('LineRunnerComponent destroyed and cleaned up'); + } } \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/pie-runner/pie-runner.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/pie-runner/pie-runner.component.ts index c1a64d1..934f618 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/pie-runner/pie-runner.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/pie-runner/pie-runner.component.ts @@ -3,6 +3,10 @@ import { DashrunnerService } from '../dashrunner.service'; import { ActivatedRoute, Router } from '@angular/router'; import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; import { DashboardContentModel } from 'src/app/models/builder/dashboard'; +// Add FilterService import +import { FilterService } from '../../../dashboardnew/common-filter/filter.service'; +// Add Subscription import +import { Subscription } from 'rxjs'; @Component({ @@ -23,9 +27,15 @@ export class PieRunnerComponent implements OnInit { showlabel; JsonData; lineChartNoLabels: any[] = []; + ConnectionId: number; // Add ConnectionId property + + // Add subscriptions to unsubscribe on destroy + private subscriptions: Subscription[] = []; constructor(private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, - private router : Router,) { } + private router : Router, + // Add FilterService to constructor + private filterService: FilterService) { } public pieChartLabels: string[] = ['SciFi', 'Drama', 'Comedy']; public pieChartData: number[] = [30, 50, 20]; @@ -39,6 +49,13 @@ export class PieRunnerComponent implements OnInit { this.editId = this.route.snapshot.params.id; console.log(this.editId); + // Subscribe to filter changes + this.subscriptions.push( + this.filterService.filterState$.subscribe(filters => { + // When filters change, refresh the chart data + this.fetchChartData(); + }) + ); this.dashboardService.getById(this.editId).subscribe((data)=>{ console.log(data); @@ -66,22 +83,62 @@ export class PieRunnerComponent implements OnInit { this.YAxis = ChartObject[i].yAxis; this.showlabel = ChartObject[i].showlabel; this.ChartLegend = ChartObject[i].chartlegend; + this.ConnectionId = ChartObject[i].connection; // Add connection ID console.log(this.TableName); - this.Dashtestservive.getChartData(this.TableName,"Pie Chart",this.XAxis,this.YAxis).subscribe((Ldata) => { - console.log(Ldata); - this.JsonData = Ldata; - this.pieChartData = this.JsonData.pieChartData; - this.pieChartLabels = this.JsonData.pieChartLabels; - - },(error) => { - console.log(error); - }); + // Fetch data with filters + this.fetchChartData(); break; // No need to continue the loop once the correct placeholder is found } } }); } - + + // Fetch chart data with filter support + fetchChartData(): void { + if (this.TableName && this.XAxis && this.YAxis) { + // Convert YAxis to string if it's an array + const yAxisString = Array.isArray(this.YAxis) ? this.YAxis.join(',') : this.YAxis; + + // Get filter parameters from common filters + const commonFilters = this.filterService.getFilterValues(); + const filterDefinitions = this.filterService.getFilters(); + + // Build filter object using field names as keys + const filterObj = {}; + Object.keys(commonFilters).forEach(filterId => { + const filterValue = commonFilters[filterId]; + + // Find the filter definition to get the field name + const filterDef = this.filterService.getFilters().find(f => f.id === filterId); + + if (filterDef && filterDef.field) { + const fieldName = filterDef.field; + if (filterValue !== undefined && filterValue !== null && filterValue !== '') { + filterObj[fieldName] = filterValue; + } + } + }); + + // Convert to JSON string for API call + let filterParams = ''; + if (Object.keys(filterObj).length > 0) { + filterParams = JSON.stringify(filterObj); + } + + console.log('PieRunner: Final filter object to send to API:', filterObj); + + // Fetch data from the dashboard service with filters + this.Dashtestservive.getChartDataWithFilters(this.TableName, "Pie Chart", this.XAxis, this.YAxis, this.ConnectionId, '', '', filterParams).subscribe((Ldata) => { + console.log(Ldata); + this.JsonData = Ldata; + this.pieChartData = this.JsonData.pieChartData; + this.pieChartLabels = this.JsonData.pieChartLabels; + },(error) => { + console.log(error); + }); + } + } + generatePDFFile(){ this.buttonClicked.emit(); const content = this.contentContainerRef.nativeElement; @@ -89,4 +146,17 @@ export class PieRunnerComponent implements OnInit { this.Dashtestservive.generatePDF(content, filename); } + + ngOnDestroy() { + // Unsubscribe from all subscriptions to prevent memory leaks + console.log('PieRunnerComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions'); + this.subscriptions.forEach(subscription => { + if (subscription && !subscription.closed) { + subscription.unsubscribe(); + } + }); + this.subscriptions = []; + + console.log('PieRunnerComponent destroyed and cleaned up'); + } } diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/polar-runner/polar-runner.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/polar-runner/polar-runner.component.ts index fdbe17a..8610693 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/polar-runner/polar-runner.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/polar-runner/polar-runner.component.ts @@ -4,6 +4,10 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; import { DashboardContentModel } from 'src/app/models/builder/dashboard'; // import { Label } from 'ng2-charts'; +// Add FilterService import +import { FilterService } from '../../../dashboardnew/common-filter/filter.service'; +// Add Subscription import +import { Subscription } from 'rxjs'; @Component({ selector: 'app-polar-runner', @@ -23,9 +27,15 @@ export class PolarRunnerComponent implements OnInit { showlabel; JsonData; lineChartNoLabels: any[] = []; + ConnectionId: number; // Add ConnectionId property + + // Add subscriptions to unsubscribe on destroy + private subscriptions: Subscription[] = []; constructor(private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, - private router : Router,) { } + private router : Router, + // Add FilterService to constructor + private filterService: FilterService) { } public polarAreaChartLabels: string[] = [ 'Download Sales', 'In-Store Sales', 'Mail Sales', 'Telesales', 'Corporate Sales' ]; public polarAreaChartData: any = [ @@ -41,6 +51,13 @@ export class PolarRunnerComponent implements OnInit { this.editId = this.route.snapshot.params.id; console.log(this.editId); + // Subscribe to filter changes + this.subscriptions.push( + this.filterService.filterState$.subscribe(filters => { + // When filters change, refresh the chart data + this.fetchChartData(); + }) + ); this.dashboardService.getById(this.editId).subscribe((data)=>{ console.log(data); @@ -66,22 +83,62 @@ export class PolarRunnerComponent implements OnInit { this.YAxis = ChartObject[i].yAxis; this.showlabel = ChartObject[i].showlabel; this.ChartLegend = ChartObject[i].chartlegend; + this.ConnectionId = ChartObject[i].connection; // Add connection ID console.log(this.TableName); - this.Dashtestservive.getChartData(this.TableName,"PolarArea Chart",this.XAxis,this.YAxis).subscribe((Ldata) => { - console.log(Ldata); - this.JsonData = Ldata; - this.polarAreaChartData = this.JsonData.polarAreaChartData; - this.polarAreaChartLabels = this.JsonData.polarAreaChartLabels; - - },(error) => { - console.log(error); - }); + // Fetch data with filters + this.fetchChartData(); break; // No need to continue the loop once the correct placeholder is found } } }); } - + + // Fetch chart data with filter support + fetchChartData(): void { + if (this.TableName && this.XAxis && this.YAxis) { + // Convert YAxis to string if it's an array + const yAxisString = Array.isArray(this.YAxis) ? this.YAxis.join(',') : this.YAxis; + + // Get filter parameters from common filters + const commonFilters = this.filterService.getFilterValues(); + const filterDefinitions = this.filterService.getFilters(); + + // Build filter object using field names as keys + const filterObj = {}; + Object.keys(commonFilters).forEach(filterId => { + const filterValue = commonFilters[filterId]; + + // Find the filter definition to get the field name + const filterDef = this.filterService.getFilters().find(f => f.id === filterId); + + if (filterDef && filterDef.field) { + const fieldName = filterDef.field; + if (filterValue !== undefined && filterValue !== null && filterValue !== '') { + filterObj[fieldName] = filterValue; + } + } + }); + + // Convert to JSON string for API call + let filterParams = ''; + if (Object.keys(filterObj).length > 0) { + filterParams = JSON.stringify(filterObj); + } + + console.log('PolarRunner: Final filter object to send to API:', filterObj); + + // Fetch data from the dashboard service with filters + this.Dashtestservive.getChartDataWithFilters(this.TableName, "PolarArea Chart", this.XAxis, this.YAxis, this.ConnectionId, '', '', filterParams).subscribe((Ldata) => { + console.log(Ldata); + this.JsonData = Ldata; + this.polarAreaChartData = this.JsonData.polarAreaChartData; + this.polarAreaChartLabels = this.JsonData.polarAreaChartLabels; + },(error) => { + console.log(error); + }); + } + } + generatePDFFile(){ this.buttonClicked.emit(); const content = this.contentContainerRef.nativeElement; @@ -89,5 +146,18 @@ export class PolarRunnerComponent implements OnInit { this.Dashtestservive.generatePDF(content, filename); } + + ngOnDestroy() { + // Unsubscribe from all subscriptions to prevent memory leaks + console.log('PolarRunnerComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions'); + this.subscriptions.forEach(subscription => { + if (subscription && !subscription.closed) { + subscription.unsubscribe(); + } + }); + this.subscriptions = []; + + console.log('PolarRunnerComponent destroyed and cleaned up'); + } } diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/radar-runner/radar-runner.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/radar-runner/radar-runner.component.ts index e1a901e..748802e 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/radar-runner/radar-runner.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/radar-runner/radar-runner.component.ts @@ -4,6 +4,10 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; import { DashboardContentModel } from 'src/app/models/builder/dashboard'; // import { Label } from 'ng2-charts'; +// Add FilterService import +import { FilterService } from '../../../dashboardnew/common-filter/filter.service'; +// Add Subscription import +import { Subscription } from 'rxjs'; @Component({ selector: 'app-radar-runner', @@ -24,9 +28,15 @@ export class RadarRunnerComponent implements OnInit { JsonData; lineChartNoLabels: any[] = []; ChartLegend = false; + ConnectionId: number; // Add ConnectionId property + + // Add subscriptions to unsubscribe on destroy + private subscriptions: Subscription[] = []; constructor(private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, - private router : Router,) { } + private router : Router, + // Add FilterService to constructor + private filterService: FilterService) { } public radarChartLabels: string[] = [ "Eating", @@ -50,6 +60,13 @@ export class RadarRunnerComponent implements OnInit { this.editId = this.route.snapshot.params.id; console.log(this.editId); + // Subscribe to filter changes + this.subscriptions.push( + this.filterService.filterState$.subscribe(filters => { + // When filters change, refresh the chart data + this.fetchChartData(); + }) + ); this.dashboardService.getById(this.editId).subscribe((data)=>{ console.log(data); @@ -75,22 +92,62 @@ export class RadarRunnerComponent implements OnInit { this.YAxis = ChartObject[i].yAxis; this.showlabel = ChartObject[i].showlabel; this.ChartLegend = ChartObject[i].chartlegend; + this.ConnectionId = ChartObject[i].connection; // Add connection ID console.log(this.TableName); - this.Dashtestservive.getChartData(this.TableName,"Radar Chart",this.XAxis,this.YAxis).subscribe((Ldata) => { - console.log(Ldata); - this.JsonData = Ldata; - this.radarChartData = this.JsonData.radarChartData; - this.radarChartLabels = this.JsonData.radarChartLabels; - - },(error) => { - console.log(error); - }); + // Fetch data with filters + this.fetchChartData(); break; // No need to continue the loop once the correct placeholder is found } } }); } - + + // Fetch chart data with filter support + fetchChartData(): void { + if (this.TableName && this.XAxis && this.YAxis) { + // Convert YAxis to string if it's an array + const yAxisString = Array.isArray(this.YAxis) ? this.YAxis.join(',') : this.YAxis; + + // Get filter parameters from common filters + const commonFilters = this.filterService.getFilterValues(); + const filterDefinitions = this.filterService.getFilters(); + + // Build filter object using field names as keys + const filterObj = {}; + Object.keys(commonFilters).forEach(filterId => { + const filterValue = commonFilters[filterId]; + + // Find the filter definition to get the field name + const filterDef = this.filterService.getFilters().find(f => f.id === filterId); + + if (filterDef && filterDef.field) { + const fieldName = filterDef.field; + if (filterValue !== undefined && filterValue !== null && filterValue !== '') { + filterObj[fieldName] = filterValue; + } + } + }); + + // Convert to JSON string for API call + let filterParams = ''; + if (Object.keys(filterObj).length > 0) { + filterParams = JSON.stringify(filterObj); + } + + console.log('RadarRunner: Final filter object to send to API:', filterObj); + + // Fetch data from the dashboard service with filters + this.Dashtestservive.getChartDataWithFilters(this.TableName, "Radar Chart", this.XAxis, this.YAxis, this.ConnectionId, '', '', filterParams).subscribe((Ldata) => { + console.log(Ldata); + this.JsonData = Ldata; + this.radarChartData = this.JsonData.radarChartData; + this.radarChartLabels = this.JsonData.radarChartLabels; + },(error) => { + console.log(error); + }); + } + } + generatePDFFile(){ this.buttonClicked.emit(); const content = this.contentContainerRef.nativeElement; @@ -98,5 +155,18 @@ export class RadarRunnerComponent implements OnInit { this.Dashtestservive.generatePDF(content, filename); } + + ngOnDestroy() { + // Unsubscribe from all subscriptions to prevent memory leaks + console.log('RadarRunnerComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions'); + this.subscriptions.forEach(subscription => { + if (subscription && !subscription.closed) { + subscription.unsubscribe(); + } + }); + this.subscriptions = []; + + console.log('RadarRunnerComponent destroyed and cleaned up'); + } } diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/scatter-runner/scatter-runner.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/scatter-runner/scatter-runner.component.ts index 2f36596..a6780d0 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/scatter-runner/scatter-runner.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/scatter-runner/scatter-runner.component.ts @@ -5,6 +5,10 @@ import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; import { DashboardContentModel } from 'src/app/models/builder/dashboard'; // import { Label } from 'ng2-charts'; import { ChartDataset } from 'chart.js'; +// Add FilterService import +import { FilterService } from '../../../dashboardnew/common-filter/filter.service'; +// Add Subscription import +import { Subscription } from 'rxjs'; @Component({ selector: 'app-scatter-runner', @@ -25,9 +29,15 @@ export class ScatterRunnerComponent implements OnInit { JsonData; lineChartNoLabels: any[] = []; ChartLegend = false; + ConnectionId: number; // Add ConnectionId property + + // Add subscriptions to unsubscribe on destroy + private subscriptions: Subscription[] = []; constructor(private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, - private router : Router,) { } + private router : Router, + // Add FilterService to constructor + private filterService: FilterService) { } public scatterChartLabels: string[] = [ 'Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running' ]; @@ -69,6 +79,13 @@ export class ScatterRunnerComponent implements OnInit { this.editId = this.route.snapshot.params.id; console.log(this.editId); + // Subscribe to filter changes + this.subscriptions.push( + this.filterService.filterState$.subscribe(filters => { + // When filters change, refresh the chart data + this.fetchChartData(); + }) + ); this.dashboardService.getById(this.editId).subscribe((data)=>{ console.log(data); @@ -94,22 +111,62 @@ export class ScatterRunnerComponent implements OnInit { this.YAxis = ChartObject[i].yAxis; this.showlabel = ChartObject[i].showlabel; this.ChartLegend = ChartObject[i].chartlegend; + this.ConnectionId = ChartObject[i].connection; // Add connection ID console.log(this.TableName); - this.Dashtestservive.getChartData(this.TableName,"Scatter Chart",this.XAxis,this.YAxis).subscribe((Ldata) => { - console.log(Ldata); - this.JsonData = Ldata; - this.scatterChartData = this.JsonData.scatterChartData; - this.scatterChartLabels = this.JsonData.scatterChartLabels; - - },(error) => { - console.log(error); - }); + // Fetch data with filters + this.fetchChartData(); break; // No need to continue the loop once the correct placeholder is found } } }); } - + + // Fetch chart data with filter support + fetchChartData(): void { + if (this.TableName && this.XAxis && this.YAxis) { + // Convert YAxis to string if it's an array + const yAxisString = Array.isArray(this.YAxis) ? this.YAxis.join(',') : this.YAxis; + + // Get filter parameters from common filters + const commonFilters = this.filterService.getFilterValues(); + const filterDefinitions = this.filterService.getFilters(); + + // Build filter object using field names as keys + const filterObj = {}; + Object.keys(commonFilters).forEach(filterId => { + const filterValue = commonFilters[filterId]; + + // Find the filter definition to get the field name + const filterDef = this.filterService.getFilters().find(f => f.id === filterId); + + if (filterDef && filterDef.field) { + const fieldName = filterDef.field; + if (filterValue !== undefined && filterValue !== null && filterValue !== '') { + filterObj[fieldName] = filterValue; + } + } + }); + + // Convert to JSON string for API call + let filterParams = ''; + if (Object.keys(filterObj).length > 0) { + filterParams = JSON.stringify(filterObj); + } + + console.log('ScatterRunner: Final filter object to send to API:', filterObj); + + // Fetch data from the dashboard service with filters + this.Dashtestservive.getChartDataWithFilters(this.TableName, "Scatter Chart", this.XAxis, this.YAxis, this.ConnectionId, '', '', filterParams).subscribe((Ldata) => { + console.log(Ldata); + this.JsonData = Ldata; + this.scatterChartData = this.JsonData.scatterChartData; + this.scatterChartLabels = this.JsonData.scatterChartLabels; + },(error) => { + console.log(error); + }); + } + } + generatePDFFile(){ this.buttonClicked.emit(); const content = this.contentContainerRef.nativeElement; @@ -117,5 +174,18 @@ export class ScatterRunnerComponent implements OnInit { this.Dashtestservive.generatePDF(content, filename); } + + ngOnDestroy() { + // Unsubscribe from all subscriptions to prevent memory leaks + console.log('ScatterRunnerComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions'); + this.subscriptions.forEach(subscription => { + if (subscription && !subscription.closed) { + subscription.unsubscribe(); + } + }); + this.subscriptions = []; + + console.log('ScatterRunnerComponent destroyed and cleaned up'); + } } diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/todo-runner/todo-runner.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/todo-runner/todo-runner.component.ts index cb264cb..a6ea095 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/todo-runner/todo-runner.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardrunner/dashrunnerline/todo-runner/todo-runner.component.ts @@ -3,6 +3,10 @@ import { DashrunnerService } from '../dashrunner.service'; import { DashboardContentModel } from 'src/app/models/builder/dashboard'; import { ActivatedRoute, Router } from '@angular/router'; import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; +// Add FilterService import +import { FilterService } from '../../../dashboardnew/common-filter/filter.service'; +// Add Subscription import +import { Subscription } from 'rxjs'; @Component({ selector: 'app-todo-runner', @@ -12,19 +16,21 @@ import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; export class TodoRunnerComponent implements OnInit { @ViewChild('contentContainer') contentContainerRef!: ElementRef; @Output() buttonClicked = new EventEmitter(); - constructor( private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, - private router : Router) { } - - loading = false; - givendata; - error; - XAxis; - YAxis; - editId; - public DashtestboardArray: DashboardContentModel[] = []; - workflowLine; - TableName; + // Add subscriptions to unsubscribe on destroy + private subscriptions: Subscription[] = []; + + loading = false; + givendata; + error; + XAxis; + YAxis; + + editId; + public DashtestboardArray: DashboardContentModel[] = []; + workflowLine; + TableName; + ConnectionId: number; // Add ConnectionId property list; data: any; @@ -34,11 +40,25 @@ export class TodoRunnerComponent implements OnInit { listName: "title123", List:['todo 1','todo 2'], } + + constructor( private Dashtestservive:DashrunnerService,private route: ActivatedRoute,private dashboardService: Dashboard3Service, + private router : Router, + // Add FilterService to constructor + private filterService: FilterService) { } + ngOnInit(): void { this.editId = this.route.snapshot.params.id; console.log(this.editId); // this.getbyId(); + // Subscribe to filter changes + this.subscriptions.push( + this.filterService.filterState$.subscribe(filters => { + // When filters change, refresh the todo data + this.fetchTodoData(); + }) + ); + this.dashboardService.getById(this.editId).subscribe((data)=>{ console.log(data); this.workflowLine = data.dashbord1_Line[0].model; @@ -63,15 +83,10 @@ export class TodoRunnerComponent implements OnInit { this.TableName = ChartObject[i].table; this.XAxis = ChartObject[i].xAxis; this.YAxis = ChartObject[i].yAxis; + this.ConnectionId = ChartObject[i].connection; // Add connection ID console.log(this.TableName); - this.Dashtestservive.getChartData(this.TableName,"Todo List",this.XAxis,this.YAxis).subscribe((Ldata) => { - console.log(Ldata); - this.todoList.listName = Ldata.listName; - this.todoList.List = Ldata.List; - - },(error) => { - console.log(error); - }); + // Fetch data with filters + this.fetchTodoData(); break; // No need to continue the loop once the correct placeholder is found } } @@ -100,4 +115,58 @@ generatePDFFile(){ this.Dashtestservive.generatePDF(content, filename); } + +// Fetch todo data with filter support +fetchTodoData(): void { + if (this.TableName && this.XAxis && this.YAxis) { + // Get filter parameters from common filters + const commonFilters = this.filterService.getFilterValues(); + + // Build filter object using field names as keys + const filterObj = {}; + Object.keys(commonFilters).forEach(filterId => { + const filterValue = commonFilters[filterId]; + + // Find the filter definition to get the field name + const filterDef = this.filterService.getFilters().find(f => f.id === filterId); + + if (filterDef && filterDef.field) { + const fieldName = filterDef.field; + if (filterValue !== undefined && filterValue !== null && filterValue !== '') { + filterObj[fieldName] = filterValue; + } + } + }); + + // Convert to JSON string for API call + let filterParams = ''; + if (Object.keys(filterObj).length > 0) { + filterParams = JSON.stringify(filterObj); + } + + console.log('TodoRunner: Final filter object to send to API:', filterObj); + + // Fetch data from the dashboard service with filters + this.Dashtestservive.getChartDataWithFilters(this.TableName, "Todo List", this.XAxis, this.YAxis, this.ConnectionId, '', '', filterParams).subscribe((Ldata) => { + console.log(Ldata); + this.todoList.listName = Ldata.listName; + this.todoList.List = Ldata.List; + },(error) => { + console.log(error); + }); + } } + +ngOnDestroy() { + // Unsubscribe from all subscriptions to prevent memory leaks + console.log('TodoRunnerComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions'); + this.subscriptions.forEach(subscription => { + if (subscription && !subscription.closed) { + subscription.unsubscribe(); + } + }); + this.subscriptions = []; + + console.log('TodoRunnerComponent destroyed and cleaned up'); +} +} \ No newline at end of file