chart
This commit is contained in:
		
							parent
							
								
									fcbee92929
								
							
						
					
					
						commit
						7461521a90
					
				| @ -227,8 +227,8 @@ | ||||
|               <div class="clr-col-sm-5"> | ||||
|                 <select [(ngModel)]="filter.field" [ngModelOptions]="{standalone: true}" class="clr-select"> | ||||
|                   <option value="">Select Field</option> | ||||
|                   <!-- Use columnData for base API filters when drilldown is not enabled, drilldownColumnData when it is --> | ||||
|                   <option *ngFor="let column of getAvailableFields(gadgetsEditdata.baseFilters, i, gadgetsEditdata.drilldownEnabled ? drilldownColumnData : columnData)" [value]="column">{{column}}</option> | ||||
|                   <!-- Base API filters should always use columnData, not drilldownColumnData --> | ||||
|                   <option *ngFor="let column of getAvailableFields(gadgetsEditdata.baseFilters, i, columnData)" [value]="column">{{column}}</option> | ||||
|                 </select> | ||||
|               </div> | ||||
|                | ||||
| @ -324,17 +324,17 @@ | ||||
|           <h5>Base Drilldown Filters</h5> | ||||
|           <div class="clr-subtext">Configure filters for the base drilldown level</div> | ||||
|            | ||||
|           <!-- Add Base Filter Button --> | ||||
|           <button class="btn btn-sm btn-primary" (click)="addBaseFilter()" style="margin-top: 10px; margin-bottom: 10px;"> | ||||
|           <!-- Add Base Drilldown Filter Button --> | ||||
|           <button class="btn btn-sm btn-primary" (click)="addDrilldownFilter()" style="margin-top: 10px; margin-bottom: 10px;"> | ||||
|             <clr-icon shape="plus"></clr-icon> Add Filter | ||||
|           </button> | ||||
|            | ||||
|           <!-- Base Filter Fields List --> | ||||
|           <div *ngFor="let filter of gadgetsEditdata.baseFilters; let i = index"  | ||||
|           <!-- Base Drilldown Filter Fields List --> | ||||
|           <div *ngFor="let filter of gadgetsEditdata.drilldownFilters; let i = index"  | ||||
|                style="margin-bottom: 10px; padding: 8px; border: 1px solid #eee; border-radius: 4px; background-color: #f9f9f9;"> | ||||
|             <div style="display: flex; justify-content: space-between; align-items: center;"> | ||||
|               <span>Filter {{i + 1}}</span> | ||||
|               <button class="btn btn-icon btn-danger btn-sm" (click)="removeBaseFilter(i)"> | ||||
|               <button class="btn btn-icon btn-danger btn-sm" (click)="removeDrilldownFilter(i)"> | ||||
|                 <clr-icon shape="trash"></clr-icon> | ||||
|               </button> | ||||
|             </div> | ||||
| @ -343,7 +343,7 @@ | ||||
|               <div class="clr-col-sm-5"> | ||||
|                 <select [(ngModel)]="filter.field" [ngModelOptions]="{standalone: true}" class="clr-select"> | ||||
|                   <option value="">Select Field</option> | ||||
|                   <option *ngFor="let column of getAvailableFields(gadgetsEditdata.baseFilters, i, drilldownColumnData)" [value]="column">{{column}}</option> | ||||
|                   <option *ngFor="let column of getAvailableFields(gadgetsEditdata.drilldownFilters, i, drilldownColumnData)" [value]="column">{{column}}</option> | ||||
|                 </select> | ||||
|               </div> | ||||
|                | ||||
| @ -353,7 +353,7 @@ | ||||
|               </div> | ||||
|                | ||||
|               <div class="clr-col-sm-2"> | ||||
|                 <button class="btn btn-icon btn-danger btn-sm" (click)="removeBaseFilter(i)"> | ||||
|                 <button class="btn btn-icon btn-danger btn-sm" (click)="removeDrilldownFilter(i)"> | ||||
|                   <clr-icon shape="trash"></clr-icon> | ||||
|                 </button> | ||||
|               </div> | ||||
|  | ||||
| @ -142,7 +142,8 @@ export class EditnewdashComponent implements OnInit { | ||||
|     drilldownXAxis: '', | ||||
|     drilldownYAxis: '', | ||||
|     drilldownParameter: '', // Add drilldown parameter property
 | ||||
|     baseFilters: [] as any[], // Add base filters
 | ||||
|     baseFilters: [] as any[], // Add base filters for API
 | ||||
|     drilldownFilters: [] as any[], // Add separate drilldown filters
 | ||||
|     // Multi-layer drilldown configurations
 | ||||
|     drilldownLayers: [] as any[], | ||||
|   }; | ||||
| @ -530,6 +531,11 @@ export class EditnewdashComponent implements OnInit { | ||||
|       this.gadgetsEditdata['baseFilters'] = [];  | ||||
|     } | ||||
|      | ||||
|     // Initialize drilldown filters if not present
 | ||||
|     if (item['drilldownFilters'] === undefined) {  | ||||
|       this.gadgetsEditdata['drilldownFilters'] = [];  | ||||
|     } | ||||
|      | ||||
|     // Initialize drilldown layers if not present
 | ||||
|     if (item['drilldownLayers'] === undefined) {  | ||||
|       this.gadgetsEditdata['drilldownLayers'] = [];  | ||||
| @ -550,6 +556,11 @@ export class EditnewdashComponent implements OnInit { | ||||
|     // Reset drilldown column data
 | ||||
|     this.drilldownColumnData = []; | ||||
|      | ||||
|     // If drilldown is enabled and we have a drilldown API URL, fetch the drilldown column data
 | ||||
|     if (this.gadgetsEditdata.drilldownEnabled && this.gadgetsEditdata.drilldownApiUrl) { | ||||
|       this.refreshBaseDrilldownColumns(); | ||||
|     } | ||||
|      | ||||
|     if (item.datastore !== undefined || '' || null) { | ||||
|       const datastore = item.datastore; | ||||
|       this.getTables(datastore); | ||||
| @ -649,6 +660,7 @@ export class EditnewdashComponent implements OnInit { | ||||
|         xyz.drilldownYAxis = this.gadgetsEditdata.drilldownYAxis; | ||||
|         xyz.drilldownParameter = this.gadgetsEditdata.drilldownParameter; | ||||
|         xyz.baseFilters = this.gadgetsEditdata.baseFilters; // Add base filters
 | ||||
|         xyz.drilldownFilters = this.gadgetsEditdata.drilldownFilters; // Add drilldown filters
 | ||||
|         xyz.drilldownLayers = this.gadgetsEditdata.drilldownLayers; | ||||
|          | ||||
|         console.log(xyz); | ||||
| @ -693,6 +705,7 @@ export class EditnewdashComponent implements OnInit { | ||||
|       drilldownYAxis: item['drilldownYAxis'], | ||||
|       drilldownParameter: item['drilldownParameter'], // Add drilldown parameter
 | ||||
|       baseFilters: item['baseFilters'] || [], // Add base filters
 | ||||
|       drilldownFilters: item['drilldownFilters'] || [], // Add drilldown filters
 | ||||
|       // Multi-layer drilldown configurations
 | ||||
|       drilldownLayers: item['drilldownLayers'] || [] | ||||
|     }; | ||||
| @ -740,6 +753,7 @@ export class EditnewdashComponent implements OnInit { | ||||
|         updatedItem.drilldownYAxis = this.gadgetsEditdata.drilldownYAxis; | ||||
|         updatedItem.drilldownParameter = this.gadgetsEditdata.drilldownParameter; | ||||
|         updatedItem.baseFilters = this.gadgetsEditdata.baseFilters; // Add base filters
 | ||||
|         updatedItem.drilldownFilters = this.gadgetsEditdata.drilldownFilters; // Add drilldown filters
 | ||||
|         updatedItem.drilldownLayers = this.gadgetsEditdata.drilldownLayers; | ||||
|          | ||||
|         console.log('Updated item:', updatedItem); | ||||
| @ -973,6 +987,20 @@ export class EditnewdashComponent implements OnInit { | ||||
|     this.gadgetsEditdata.baseFilters.splice(index, 1); | ||||
|   } | ||||
|    | ||||
|   // Add method to add a drilldown filter
 | ||||
|   addDrilldownFilter() { | ||||
|     const newFilter = { | ||||
|       field: '', | ||||
|       value: '' | ||||
|     }; | ||||
|     this.gadgetsEditdata.drilldownFilters.push(newFilter); | ||||
|   } | ||||
|    | ||||
|   // Add method to remove a drilldown filter
 | ||||
|   removeDrilldownFilter(index: number) { | ||||
|     this.gadgetsEditdata.drilldownFilters.splice(index, 1); | ||||
|   } | ||||
|    | ||||
|   // Add method to add a layer filter
 | ||||
|   addLayerFilter(layerIndex: number) { | ||||
|     const newFilter = { | ||||
|  | ||||
| @ -30,6 +30,7 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -72,6 +73,7 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -80,7 +82,7 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -296,10 +298,31 @@ export class BarChartComponent implements OnInit, OnChanges, OnDestroy { | ||||
|         filterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown layer filter parameters:', filterParams); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     const subscription = this.dashboardService.getChartData(actualApiUrl, 'bar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // For drilldown level, we pass the parameter value from the drilldown stack and drilldown filters
 | ||||
|     const subscription = this.dashboardService.getChartData( | ||||
|       drilldownConfig.apiUrl, 'bar',  | ||||
|       this.drilldownXAxis, this.drilldownYAxis,  | ||||
|       this.connection,  | ||||
|       parameterField, parameterValue, | ||||
|       drilldownFilterParams | ||||
|     ).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -30,6 +30,7 @@ export class BubbleChartComponent implements OnInit, OnChanges { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -110,6 +111,7 @@ export class BubbleChartComponent implements OnInit, OnChanges { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -118,7 +120,7 @@ export class BubbleChartComponent implements OnInit, OnChanges { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -305,13 +307,32 @@ export class BubbleChartComponent implements OnInit, OnChanges { | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/bubble?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'bubble', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'bubble', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -29,6 +29,7 @@ export class DoughnutChartComponent implements OnInit, OnChanges, AfterViewCheck | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -153,6 +154,7 @@ export class DoughnutChartComponent implements OnInit, OnChanges, AfterViewCheck | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -161,7 +163,7 @@ export class DoughnutChartComponent implements OnInit, OnChanges, AfterViewCheck | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -400,13 +402,32 @@ export class DoughnutChartComponent implements OnInit, OnChanges, AfterViewCheck | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/doughnut?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'doughnut', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'doughnut', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -31,6 +31,7 @@ export class DynamicChartComponent implements OnInit, OnChanges { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -52,6 +53,7 @@ export class DynamicChartComponent implements OnInit, OnChanges { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -60,7 +62,7 @@ export class DynamicChartComponent implements OnInit, OnChanges { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -296,13 +298,32 @@ export class DynamicChartComponent implements OnInit, OnChanges { | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/dynamic?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'dynamic', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'dynamic', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -29,6 +29,7 @@ export class FinancialChartComponent implements OnInit, OnChanges { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -48,6 +49,7 @@ export class FinancialChartComponent implements OnInit, OnChanges { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -56,7 +58,7 @@ export class FinancialChartComponent implements OnInit, OnChanges { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -287,13 +289,32 @@ export class FinancialChartComponent implements OnInit, OnChanges { | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/financial?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'financial', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'financial', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -29,6 +29,7 @@ export class LineChartComponent implements OnInit, OnChanges { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -98,6 +99,7 @@ export class LineChartComponent implements OnInit, OnChanges { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -106,7 +108,7 @@ export class LineChartComponent implements OnInit, OnChanges { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -311,13 +313,32 @@ export class LineChartComponent implements OnInit, OnChanges { | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/line?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'line', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'line', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -29,6 +29,7 @@ export class PieChartComponent implements OnInit, OnChanges, AfterViewChecked { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -122,6 +123,7 @@ export class PieChartComponent implements OnInit, OnChanges, AfterViewChecked { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -130,7 +132,7 @@ export class PieChartComponent implements OnInit, OnChanges, AfterViewChecked { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -360,13 +362,32 @@ export class PieChartComponent implements OnInit, OnChanges, AfterViewChecked { | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/pie?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'pie', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'pie', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -1,28 +1,10 @@ | ||||
| 
 | ||||
| <div style="display: block"> | ||||
|   <!-- Drilldown mode indicator --> | ||||
|   <div *ngIf="currentDrilldownLevel > 0" style="background-color: #e0e0e0; padding: 5px; margin-bottom: 10px; border-radius: 4px; text-align: center;"> | ||||
|     <span style="font-weight: bold; color: #333;">Drilldown Level: {{currentDrilldownLevel}}</span> | ||||
|     <button (click)="navigateBack()" style="margin-left: 10px; padding: 2px 8px; background-color: #007cba; color: white; border: none; border-radius: 3px; cursor: pointer;"> | ||||
|       Back to Level {{currentDrilldownLevel - 1}} | ||||
|     </button> | ||||
|     <button (click)="resetToOriginalData()" style="margin-left: 10px; padding: 2px 8px; background-color: #dc3545; color: white; border: none; border-radius: 3px; cursor: pointer;"> | ||||
|       Back to Main View | ||||
|     </button> | ||||
|   </div> | ||||
|    | ||||
|   <!-- No data message --> | ||||
|   <div *ngIf="noDataAvailable" style="text-align: center; padding: 20px; color: #666; font-style: italic;"> | ||||
|     No data available | ||||
|   </div> | ||||
|    | ||||
|   <!-- Chart display --> | ||||
|   <div *ngIf="!noDataAvailable"> | ||||
|   <canvas baseChart | ||||
|       [data]="polarAreaChartData" | ||||
|     [datasets]="polarAreaChartData" | ||||
|     [labels]="polarAreaChartLabels" | ||||
|     [type]="polarAreaChartType" | ||||
|     (chartHover)="chartHovered($event)" | ||||
|    (chartClick)="chartClicked($event)"> | ||||
|   </canvas> | ||||
|   </div> | ||||
| </div> | ||||
| @ -0,0 +1,18 @@ | ||||
| // Polar Chart Component Styles | ||||
| div[style*="display: block"] { | ||||
|   position: relative; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
| } | ||||
| 
 | ||||
| canvas { | ||||
|   max-width: 100%; | ||||
|   max-height: 100%; | ||||
| } | ||||
| 
 | ||||
| // Ensure the chart container has proper sizing | ||||
| :host { | ||||
|   display: block; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
| } | ||||
| @ -1,12 +1,13 @@ | ||||
| import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core'; | ||||
| import { Dashboard3Service } from 'src/app/services/builder/dashboard3.service'; | ||||
| import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; | ||||
| import { Dashboard3Service } from '../../../../../../services/builder/dashboard3.service'; | ||||
| import { Subscription } from 'rxjs'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-polar-chart', | ||||
|   templateUrl: './polar-chart.component.html', | ||||
|   styleUrls: ['./polar-chart.component.scss'] | ||||
| }) | ||||
| export class PolarChartComponent implements OnInit, OnChanges { | ||||
| export class PolarChartComponent implements OnInit, OnChanges, OnDestroy { | ||||
|   @Input() xAxis: string; | ||||
|   @Input() yAxis: string | string[]; | ||||
|   @Input() table: string; | ||||
| @ -29,11 +30,30 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
|   constructor(private dashboardService: Dashboard3Service) { } | ||||
| 
 | ||||
|   public polarAreaChartLabels: string[] = [ 'Download Sales', 'In-Store Sales', 'Mail Sales', 'Telesales', 'Corporate Sales' ]; | ||||
|   public polarAreaChartData: any = [ | ||||
|     { data: [ 300, 500, 100, 40, 120 ], label: 'Series 1'} | ||||
|   ]; | ||||
|   public polarAreaChartType: string = 'polarArea'; | ||||
|    | ||||
|   // Multi-layer drilldown state tracking
 | ||||
|   drilldownStack: any[] = []; // Stack to track drilldown navigation history
 | ||||
|   currentDrilldownLevel: number = 0; // Current drilldown level (0 = base level)
 | ||||
|   originalPolarAreaChartLabels: string[] = []; | ||||
|   originalPolarAreaChartData: any = []; | ||||
|    | ||||
|   // No data state
 | ||||
|   noDataAvailable: boolean = false; | ||||
|    | ||||
|   // Flag to prevent infinite loops
 | ||||
|   private isFetchingData: boolean = false; | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|     // Initialize with default data
 | ||||
|     this.fetchChartData(); | ||||
| @ -48,6 +68,7 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -56,7 +77,7 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -64,25 +85,6 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   public polarAreaChartLabels: string[] = [ 'Download Sales', 'In-Store Sales', 'Mail Sales', 'Telesales', 'Corporate Sales' ]; | ||||
|   public polarAreaChartData: any = [ | ||||
|     { data: [ 300, 500, 100, 40, 120 ], label: 'Series 1'} | ||||
|   ]; | ||||
| 
 | ||||
|   public polarAreaChartType: string = 'polarArea'; | ||||
|    | ||||
|   // Multi-layer drilldown state tracking
 | ||||
|   drilldownStack: any[] = []; // Stack to track drilldown navigation history
 | ||||
|   currentDrilldownLevel: number = 0; // Current drilldown level (0 = base level)
 | ||||
|   originalPolarAreaChartLabels: string[] = []; | ||||
|   originalPolarAreaChartData: any = []; | ||||
|    | ||||
|   // No data state
 | ||||
|   noDataAvailable: boolean = false; | ||||
|    | ||||
|   // Flag to prevent infinite loops
 | ||||
|   private isFetchingData: boolean = false; | ||||
|    | ||||
|   fetchChartData(): void { | ||||
|     // Set flag to prevent recursive calls
 | ||||
|     this.isFetchingData = true; | ||||
| @ -131,6 +133,8 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|             this.noDataAvailable = true; | ||||
|             this.polarAreaChartLabels = []; | ||||
|             this.polarAreaChartData = []; | ||||
|             // Validate and sanitize data to show default data
 | ||||
|             this.validateChartData(); | ||||
|             // Reset flag after fetching
 | ||||
|             this.isFetchingData = false; | ||||
|             return; | ||||
| @ -141,26 +145,36 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|             // For polar charts, we need to extract the data differently
 | ||||
|             // The first dataset's data array contains the values for the polar chart
 | ||||
|             this.noDataAvailable = data.chartLabels.length === 0; | ||||
|             this.polarAreaChartLabels = data.chartLabels; | ||||
|             this.polarAreaChartLabels = data.chartLabels || []; | ||||
|             if (data.chartData && data.chartData.length > 0) { | ||||
|               this.polarAreaChartData = data.chartData[0].data.map(value => { | ||||
|                 // Convert to number if it's not already
 | ||||
|                 return isNaN(Number(value)) ? 0 : Number(value); | ||||
|                 const numValue = Number(value); | ||||
|                 return isNaN(numValue) ? 0 : numValue; | ||||
|               }); | ||||
|             } else { | ||||
|               this.polarAreaChartData = []; | ||||
|             } | ||||
|             // Ensure labels and data arrays have the same length
 | ||||
|             this.syncLabelAndDataArrays(); | ||||
|             // Validate and sanitize data
 | ||||
|             this.validateChartData(); | ||||
|             // Trigger change detection
 | ||||
|             this.polarAreaChartData = [...this.polarAreaChartData]; | ||||
|             console.log('Updated polar chart with data:', { labels: this.polarAreaChartLabels, data: this.polarAreaChartData }); | ||||
|           } else if (data && data.labels && data.data) { | ||||
|             // Handle the original expected format as fallback
 | ||||
|             this.noDataAvailable = data.labels.length === 0; | ||||
|             this.polarAreaChartLabels = data.labels; | ||||
|             this.polarAreaChartLabels = data.labels || []; | ||||
|             this.polarAreaChartData = data.data.map(value => { | ||||
|               // Convert to number if it's not already
 | ||||
|               return isNaN(Number(value)) ? 0 : Number(value); | ||||
|               const numValue = Number(value); | ||||
|               return isNaN(numValue) ? 0 : numValue; | ||||
|             }); | ||||
|             // Ensure labels and data arrays have the same length
 | ||||
|             this.syncLabelAndDataArrays(); | ||||
|             // Validate and sanitize data
 | ||||
|             this.validateChartData(); | ||||
|             // Trigger change detection
 | ||||
|             this.polarAreaChartData = [...this.polarAreaChartData]; | ||||
|             console.log('Updated polar chart with legacy data format:', { labels: this.polarAreaChartLabels, data: this.polarAreaChartData }); | ||||
| @ -169,6 +183,8 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|             this.noDataAvailable = true; | ||||
|             this.polarAreaChartLabels = []; | ||||
|             this.polarAreaChartData = []; | ||||
|             // Validate and sanitize data
 | ||||
|             this.validateChartData(); | ||||
|           } | ||||
|           // Reset flag after fetching
 | ||||
|           this.isFetchingData = false; | ||||
| @ -178,6 +194,8 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|           this.noDataAvailable = true; | ||||
|           this.polarAreaChartLabels = []; | ||||
|           this.polarAreaChartData = []; | ||||
|           // Validate and sanitize data to show default data
 | ||||
|           this.validateChartData(); | ||||
|           // Reset flag after fetching
 | ||||
|           this.isFetchingData = false; | ||||
|           // Keep default data in case of error
 | ||||
| @ -188,6 +206,8 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|       this.noDataAvailable = true; | ||||
|       this.polarAreaChartLabels = []; | ||||
|       this.polarAreaChartData = []; | ||||
|       // Validate and sanitize data to show default data
 | ||||
|       this.validateChartData(); | ||||
|       // Reset flag after fetching
 | ||||
|       this.isFetchingData = false; | ||||
|     } | ||||
| @ -285,13 +305,32 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/polar?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'polar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'polar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
| @ -307,26 +346,36 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|           // For polar charts, we need to extract the data differently
 | ||||
|           // The first dataset's data array contains the values for the polar chart
 | ||||
|           this.noDataAvailable = data.chartLabels.length === 0; | ||||
|           this.polarAreaChartLabels = data.chartLabels; | ||||
|           this.polarAreaChartLabels = data.chartLabels || []; | ||||
|           if (data.chartData && data.chartData.length > 0) { | ||||
|             this.polarAreaChartData = data.chartData[0].data.map(value => { | ||||
|               // Convert to number if it's not already
 | ||||
|               return isNaN(Number(value)) ? 0 : Number(value); | ||||
|               const numValue = Number(value); | ||||
|               return isNaN(numValue) ? 0 : numValue; | ||||
|             }); | ||||
|           } else { | ||||
|             this.polarAreaChartData = []; | ||||
|           } | ||||
|           // Ensure labels and data arrays have the same length
 | ||||
|           this.syncLabelAndDataArrays(); | ||||
|           // Validate and sanitize data
 | ||||
|           this.validateChartData(); | ||||
|           // Trigger change detection
 | ||||
|           this.polarAreaChartData = [...this.polarAreaChartData]; | ||||
|           console.log('Updated polar chart with drilldown data:', { labels: this.polarAreaChartLabels, data: this.polarAreaChartData }); | ||||
|         } else if (data && data.labels && data.data) { | ||||
|           // Handle the original expected format as fallback
 | ||||
|           this.noDataAvailable = data.labels.length === 0; | ||||
|           this.polarAreaChartLabels = data.labels; | ||||
|           this.polarAreaChartLabels = data.labels || []; | ||||
|           this.polarAreaChartData = data.data.map(value => { | ||||
|             // Convert to number if it's not already
 | ||||
|             return isNaN(Number(value)) ? 0 : Number(value); | ||||
|             const numValue = Number(value); | ||||
|             return isNaN(numValue) ? 0 : numValue; | ||||
|           }); | ||||
|           // Ensure labels and data arrays have the same length
 | ||||
|           this.syncLabelAndDataArrays(); | ||||
|           // Validate and sanitize data
 | ||||
|           this.validateChartData(); | ||||
|           // Trigger change detection
 | ||||
|           this.polarAreaChartData = [...this.polarAreaChartData]; | ||||
|           console.log('Updated polar chart with drilldown legacy data format:', { labels: this.polarAreaChartLabels, data: this.polarAreaChartData }); | ||||
| @ -335,6 +384,8 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|           this.noDataAvailable = true; | ||||
|           this.polarAreaChartLabels = []; | ||||
|           this.polarAreaChartData = []; | ||||
|           // Validate and sanitize data
 | ||||
|           this.validateChartData(); | ||||
|         } | ||||
|       }, | ||||
|       (error) => { | ||||
| @ -403,6 +454,58 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Validate and sanitize chart data | ||||
|    */ | ||||
|   private validateChartData(): void { | ||||
|     // Ensure we have valid arrays
 | ||||
|     if (!Array.isArray(this.polarAreaChartLabels)) { | ||||
|       this.polarAreaChartLabels = []; | ||||
|     } | ||||
|      | ||||
|     if (!Array.isArray(this.polarAreaChartData)) { | ||||
|       this.polarAreaChartData = []; | ||||
|     } | ||||
|      | ||||
|     // If we have no data, show default data
 | ||||
|     if (this.polarAreaChartLabels.length === 0 && this.polarAreaChartData.length === 0) { | ||||
|       // Add default data to ensure chart visibility
 | ||||
|       this.polarAreaChartLabels = ['Download Sales', 'In-Store Sales', 'Mail Sales', 'Telesales', 'Corporate Sales']; | ||||
|       this.polarAreaChartData = [300, 500, 100, 40, 120]; | ||||
|     } | ||||
|      | ||||
|     // Ensure we have matching arrays
 | ||||
|     if (this.polarAreaChartLabels.length !== this.polarAreaChartData.length) { | ||||
|       const maxLength = Math.max(this.polarAreaChartLabels.length, this.polarAreaChartData.length); | ||||
|       while (this.polarAreaChartLabels.length < maxLength) { | ||||
|         this.polarAreaChartLabels.push(`Label ${this.polarAreaChartLabels.length + 1}`); | ||||
|       } | ||||
|       while (this.polarAreaChartData.length < maxLength) { | ||||
|         this.polarAreaChartData.push(0); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   // Ensure labels and data arrays have the same length
 | ||||
|   private syncLabelAndDataArrays(): void { | ||||
|     if (this.polarAreaChartLabels && this.polarAreaChartData) { | ||||
|       const labelCount = this.polarAreaChartLabels.length; | ||||
|       const dataCount = this.polarAreaChartData.length; | ||||
|        | ||||
|       if (labelCount > dataCount) { | ||||
|         // Add zeros to data array
 | ||||
|         while (this.polarAreaChartData.length < labelCount) { | ||||
|           this.polarAreaChartData.push(0); | ||||
|         } | ||||
|       } else if (dataCount > labelCount) { | ||||
|         // Add labels to label array
 | ||||
|         while (this.polarAreaChartLabels.length < dataCount) { | ||||
|           this.polarAreaChartLabels.push(`Item ${this.polarAreaChartLabels.length + 1}`); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // events
 | ||||
|   public chartClicked(e: any): void { | ||||
|     console.log('Polar chart clicked:', e); | ||||
| @ -491,4 +594,8 @@ export class PolarChartComponent implements OnInit, OnChanges { | ||||
|   public chartHovered(e: any): void { | ||||
|     console.log(e); | ||||
|   } | ||||
|    | ||||
|   ngOnDestroy(): void { | ||||
|     // Clean up any subscriptions if needed
 | ||||
|   } | ||||
| } | ||||
| @ -29,6 +29,7 @@ export class RadarChartComponent implements OnInit, OnChanges { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -76,6 +77,7 @@ export class RadarChartComponent implements OnInit, OnChanges { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -84,7 +86,7 @@ export class RadarChartComponent implements OnInit, OnChanges { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -296,13 +298,32 @@ export class RadarChartComponent implements OnInit, OnChanges { | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/radar?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'radar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'radar', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -30,6 +30,7 @@ export class ScatterChartComponent implements OnInit, OnChanges { | ||||
|   @Input() drilldownYAxis: string; | ||||
|   @Input() drilldownParameter: string; // Add drilldown parameter input
 | ||||
|   @Input() baseFilters: any[] = []; // Add base filters input
 | ||||
|   @Input() drilldownFilters: any[] = []; // Add drilldown filters input
 | ||||
|   // Multi-layer drilldown configuration inputs
 | ||||
|   @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
 | ||||
| 
 | ||||
| @ -49,6 +50,7 @@ export class ScatterChartComponent implements OnInit, OnChanges { | ||||
|     const tableChanged = changes.table && !changes.table.firstChange; | ||||
|     const connectionChanged = changes.connection && !changes.connection.firstChange; | ||||
|     const baseFiltersChanged = changes.baseFilters && !changes.baseFilters.firstChange; | ||||
|     const drilldownFiltersChanged = changes.drilldownFilters && !changes.drilldownFilters.firstChange; | ||||
|     // Drilldown configuration changes
 | ||||
|     const drilldownEnabledChanged = changes.drilldownEnabled && !changes.drilldownEnabled.firstChange; | ||||
|     const drilldownApiUrlChanged = changes.drilldownApiUrl && !changes.drilldownApiUrl.firstChange; | ||||
| @ -57,7 +59,7 @@ export class ScatterChartComponent implements OnInit, OnChanges { | ||||
|     const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; | ||||
|      | ||||
|     // Only fetch data if the actual chart configuration changed and we're not already fetching
 | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || | ||||
|     if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || | ||||
|         drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || | ||||
|         drilldownLayersChanged)) { | ||||
|       console.log('Chart configuration changed, fetching new data'); | ||||
| @ -285,13 +287,32 @@ export class ScatterChartComponent implements OnInit, OnChanges { | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Convert drilldownFilters to filter parameters for drilldown level
 | ||||
|     let drilldownFilterParams = ''; | ||||
|     if (this.drilldownFilters && this.drilldownFilters.length > 0) { | ||||
|       const filterObj = {}; | ||||
|       this.drilldownFilters.forEach(filter => { | ||||
|         if (filter.field && filter.value) { | ||||
|           filterObj[filter.field] = filter.value; | ||||
|         } | ||||
|       }); | ||||
|       if (Object.keys(filterObj).length > 0) { | ||||
|         drilldownFilterParams = JSON.stringify(filterObj); | ||||
|       } | ||||
|     } | ||||
|     console.log('Drilldown filter parameters:', drilldownFilterParams); | ||||
|      | ||||
|     // Use drilldown filters if available, otherwise use layer filters
 | ||||
|     const finalFilterParams = drilldownFilterParams || filterParams; | ||||
|     console.log('Final filter parameters:', finalFilterParams); | ||||
|      | ||||
|     // Log the URL that will be called
 | ||||
|     const url = `chart/getdashjson/scatter?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; | ||||
|     console.log('Drilldown data URL:', url); | ||||
|      | ||||
|     // Fetch data from the dashboard service with parameter field and value
 | ||||
|     // Backend handles filtering, we just pass the parameter field and value
 | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'scatter', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe( | ||||
|     this.dashboardService.getChartData(actualApiUrl, 'scatter', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, finalFilterParams).subscribe( | ||||
|       (data: any) => { | ||||
|         console.log('Received drilldown data:', data); | ||||
|         if (data === null) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user