From c66e217b0c40ce2d4d234ece797856e1c919de9f Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Wed, 22 Oct 2025 11:11:43 +0530 Subject: [PATCH] dashboard --- .../main/builder/dashboardnew/Data_lake 3.zip | Bin 0 -> 26897 bytes .../Data_lake/Data_lake.component.html | 30 ++- .../Data_lake/Data_lake.component.ts | 197 ++++++++++++++---- .../editnewdash/FILTER_CONFIGURATION_GUIDE.md | 161 ++++++++++++++ .../editnewdash/editnewdash.component.html | 92 +++++++- .../editnewdash/editnewdash.component.ts | 60 +++++- .../gadgets/bar-chart/FILTER_CONFIGURATION.md | 142 +++++++++++++ .../FILTER_IMPLEMENTATION_SUMMARY.md | 116 +++++++++++ .../gadgets/bar-chart/USAGE_EXAMPLE.md | 86 ++++++++ .../bar-chart/bar-chart-example.component.ts | 53 +++++ .../bar-chart/bar-chart-test.component.ts | 28 +++ .../bar-chart/bar-chart.component.html | 3 + .../gadgets/bar-chart/bar-chart.component.ts | 27 ++- 13 files changed, 937 insertions(+), 58 deletions(-) create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/Data_lake 3.zip create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/FILTER_CONFIGURATION_GUIDE.md create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/FILTER_CONFIGURATION.md create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/FILTER_IMPLEMENTATION_SUMMARY.md create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/USAGE_EXAMPLE.md create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart-example.component.ts create mode 100644 frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart-test.component.ts diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/Data_lake 3.zip b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/Data_lake 3.zip new file mode 100644 index 0000000000000000000000000000000000000000..d74492d91865d14c8b2fed11d1f8deaf9e5e0a3d GIT binary patch literal 26897 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 + + + Reference Data Lake + + Calculated Fields @@ -126,6 +131,9 @@ {{user.sureconnect_name}} + + {{user.ref_datalake_name}} + @@ -154,7 +162,7 @@ - @@ -426,6 +434,15 @@ + +
+ + +
@@ -546,6 +563,15 @@
+ +
+ + +
@@ -890,4 +916,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/Data_lake/Data_lake.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/Data_lake/Data_lake.component.ts index ac4cc80..6cc9432 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/Data_lake/Data_lake.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/Data_lake/Data_lake.component.ts @@ -62,6 +62,10 @@ export class Data_lakeComponent implements OnInit { sureConnectList; selectedSureConnect: any = null; + // Data Lake reference properties + dataLakeList: any[] = []; + selectedDataLake: any = null; + // Calculated field properties calculatedFieldModalOpen = false; availableKeys: string[] = []; @@ -117,6 +121,7 @@ export class Data_lakeComponent implements OnInit { this.userrole = this.userInfoService.getRoles(); this.getData(); this.getSureConnectList(); // Fetch SureConnect list + this.getDataLakeList(); // Fetch Data Lake list for reference dropdown this.entryForm = this._fb.group({ name: [null], @@ -133,6 +138,7 @@ export class Data_lakeComponent implements OnInit { batch_volume: [null], sure_connect_id: [null], // Add SureConnect field + ref_datalake_id: [null], // Add Data Lake reference field }); // component_button200 // form code start @@ -231,6 +237,17 @@ export class Data_lakeComponent implements OnInit { }); } + // Fetch Data Lake list for reference dropdown + getDataLakeList() { + this.mainService.getAll().subscribe((data: any[]) => { + // Filter out the current item to avoid self-reference + this.dataLakeList = data.filter(item => item.id !== (this.rowSelected?.id || 0)); + console.log('Data Lake List:', this.dataLakeList); + }, (error) => { + console.log('Error fetching Data Lake list:', error); + }); + } + // Get operation symbol for display getOperationSymbol(operation: string): string { switch(operation) { @@ -245,7 +262,7 @@ export class Data_lakeComponent implements OnInit { } // Fetch available keys from API - fetchAvailableKeys(dataLakeItem: any) { + fetchAvailableKeys(dataLakeItem: any, isGroupBy: boolean = false) { if (!dataLakeItem.url || !dataLakeItem.sure_connect_id) { this.toastr.error('URL and SureConnect ID are required to fetch keys'); return; @@ -256,11 +273,56 @@ export class Data_lakeComponent implements OnInit { // Call the service method to get all keys this.mainService.fetchAvailableKeys(dataLakeItem.url, dataLakeItem.sure_connect_id).subscribe( (keys: string[]) => { - this.availableKeys = keys; + // Combine API keys with calculated field names + const calculatedFieldNames = this.getCalculatedFieldNames(); + this.availableKeys = [...keys, ...calculatedFieldNames]; + // Reset the calculated field form to ensure it starts fresh this.resetCalculatedFieldForm(); - this.calculatedFieldModalOpen = true; - console.log('Available keys:', keys); + + // Preload existing calculated fields if they exist + if (dataLakeItem.calculated_field_json) { + try { + const existingFields = JSON.parse(dataLakeItem.calculated_field_json); + if (Array.isArray(existingFields)) { + this.calculatedFields = [...existingFields]; + this.toastr.info(`Loaded ${existingFields.length} existing calculated fields`); + } + } catch (e) { + console.error('Error parsing calculated_field_json:', e); + this.calculatedFields = []; + } + } else { + this.calculatedFields = []; + } + + // Open the appropriate modal based on the context + if (isGroupBy) { + // For group by, we need to extract existing group by configurations + if (dataLakeItem.calculated_field_json) { + try { + const existingFields = JSON.parse(dataLakeItem.calculated_field_json); + if (Array.isArray(existingFields)) { + // Find group by configurations + const groupByConfigs = existingFields.filter(field => field.type === 'groupby'); + if (groupByConfigs.length > 0) { + // For simplicity, we'll load the first group by configuration + const firstConfig = groupByConfigs[0]; + this.selectedGroupByFields = [...firstConfig.groupFields]; + this.selectedAggregationFields = [...firstConfig.aggregations]; + this.toastr.info(`Loaded existing group by configuration`); + } + } + } catch (e) { + console.error('Error parsing calculated_field_json for group by:', e); + } + } + this.showGroupByModal = true; + } else { + this.calculatedFieldModalOpen = true; + } + + console.log('Available keys:', this.availableKeys); }, (error) => { console.error('Error fetching keys:', error); @@ -335,7 +397,6 @@ export class Data_lakeComponent implements OnInit { } } } - // Create calculated field object for complex equation const calculatedField = { id: Date.now(), @@ -347,6 +408,9 @@ export class Data_lakeComponent implements OnInit { this.calculatedFields.push(calculatedField); this.toastr.success('Complex calculated field added successfully'); + + // Refresh available keys to include the new calculated field + this.refreshAvailableKeys(); // Reset form but keep one empty field component this.calculatedFieldForm.reset({ @@ -419,6 +483,9 @@ export class Data_lakeComponent implements OnInit { this.calculatedFields.push(calculatedField); this.toastr.success('Calculated field added successfully'); + + // Refresh available keys to include the new calculated field + this.refreshAvailableKeys(); // Reset form but keep one empty field component this.calculatedFieldForm.reset({ @@ -609,6 +676,9 @@ export class Data_lakeComponent implements OnInit { deleteCalculatedField(id: number) { this.calculatedFields = this.calculatedFields.filter(field => field.id !== id); this.toastr.success('Calculated field deleted'); + + // Refresh available keys to reflect the deleted field + this.refreshAvailableKeys(); } onEdit(row) { @@ -616,6 +686,8 @@ export class Data_lakeComponent implements OnInit { this.editCronExpression = row.cron_job || ''; // Set the selected SureConnect for edit form this.selectedSureConnect = row.sure_connect_id || null; + // Set the selected Data Lake for edit form + this.selectedDataLake = row.ref_datalake_id || null; // Use setTimeout to ensure the component has time to initialize setTimeout(() => { this.modalEdit = true; @@ -769,6 +841,7 @@ export class Data_lakeComponent implements OnInit { this.modalAdd = true; this.addCronExpression = ''; this.selectedSureConnect = null; // Reset SureConnect selection + this.selectedDataLake = null; // Reset Data Lake selection this.submitted = false; // Reset the form control for cron_job and sure_connect_id if (this.entryForm) { @@ -801,7 +874,7 @@ export class Data_lakeComponent implements OnInit { } // Generate JSON from calculated fields and update the record - updateCalculatedFields() { + updateCalculatedFields(closeModal: boolean = true) { if (!this.selectedDataLakeItem || this.calculatedFields.length === 0) { this.toastr.error('No calculated fields to update'); return; @@ -827,8 +900,11 @@ export class Data_lakeComponent implements OnInit { this.product[index].iscalculatedfield = true; } - // Close the modal only when called directly from the UI - if (this.calculatedFieldModalOpen) { + // Refresh available keys to ensure they include the latest calculated fields + this.refreshAvailableKeys(); + + // Close the modal only when called directly from the UI and closeModal is true + if (closeModal && this.calculatedFieldModalOpen) { this.calculatedFieldModalOpen = false; } }, @@ -995,15 +1071,44 @@ export class Data_lakeComponent implements OnInit { openGroupByModal(dataLakeItem: any) { this.selectedDataLakeItem = dataLakeItem; - // Fetch available keys if not already fetched + // Fetch available keys if not already fetched or if called directly if (this.availableKeys.length === 0) { - this.fetchAvailableKeys(dataLakeItem); + this.fetchAvailableKeys(dataLakeItem, true); // Pass true to indicate group by context + } else { + // Keys are already available, just preload existing data and open modal + + // Initialize selected group by fields as empty array + this.selectedGroupByFields = []; + this.selectedAggregationFields = []; + + // Preload existing group by configurations if they exist in calculated_field_json + // (Group by configurations are stored in the same calculated_field_json field) + if (dataLakeItem.calculated_field_json) { + try { + const existingFields = JSON.parse(dataLakeItem.calculated_field_json); + if (Array.isArray(existingFields)) { + this.calculatedFields = [...existingFields]; + + // Find group by configurations + const groupByConfigs = existingFields.filter(field => field.type === 'groupby'); + if (groupByConfigs.length > 0) { + // For simplicity, we'll load the first group by configuration + const firstConfig = groupByConfigs[0]; + this.selectedGroupByFields = [...firstConfig.groupFields]; + this.selectedAggregationFields = [...firstConfig.aggregations]; + this.toastr.info(`Loaded existing group by configuration`); + } + } + } catch (e) { + console.error('Error parsing calculated_field_json:', e); + this.calculatedFields = []; + } + } else { + this.calculatedFields = []; + } + + this.showGroupByModal = true; } - - // Initialize selected group by fields as empty array - this.selectedGroupByFields = []; - this.selectedAggregationFields = []; - this.showGroupByModal = true; } // Method to add a field to group by selection @@ -1072,41 +1177,17 @@ export class Data_lakeComponent implements OnInit { // New method to update calculated fields after adding group by configuration updateCalculatedFieldsAfterGroupBy() { - if (!this.selectedDataLakeItem || this.calculatedFields.length === 0) { - return; - } - - // Convert calculated fields to JSON string - const calculatedFieldJson = JSON.stringify(this.calculatedFields); - - // Call the service method to update the record - this.mainService.updateCalculatedFields( - this.selectedDataLakeItem.id, - calculatedFieldJson, - true // iscalculatedfield = true - ).subscribe( - (response) => { - console.log('Calculated fields updated successfully:', response); - this.toastr.success('Group by configuration saved successfully'); - - // Update the local data - const index = this.product.findIndex(item => item.id === this.selectedDataLakeItem.id); - if (index !== -1) { - this.product[index].calculated_field_json = calculatedFieldJson; - this.product[index].iscalculatedfield = true; - } - }, - (error) => { - console.error('Error updating calculated fields:', error); - this.toastr.error('Failed to save group by configuration'); - } - ); + // Simply call the main update method without closing the modal + this.updateCalculatedFields(false); } // Method to remove group by configuration removeGroupByConfig(id: number) { this.calculatedFields = this.calculatedFields.filter(field => field.id !== id || field.type !== 'groupby'); this.toastr.success('Group by configuration removed'); + + // Refresh available keys to reflect the removed configuration + this.refreshAvailableKeys(); } // Method to check if a field is selected for group by @@ -1114,6 +1195,34 @@ export class Data_lakeComponent implements OnInit { return this.selectedGroupByFields.includes(field); } + // Helper method to get calculated field names + getCalculatedFieldNames(): string[] { + return this.calculatedFields + .filter(field => field.type !== 'groupby') // Exclude group by configurations + .map(field => field.fieldName); + } + + // Method to refresh available keys including calculated field names + refreshAvailableKeys() { + if (this.selectedDataLakeItem) { + // Fetch fresh keys from API and combine with calculated field names + this.mainService.fetchAvailableKeys(this.selectedDataLakeItem.url, this.selectedDataLakeItem.sure_connect_id).subscribe( + (keys: string[]) => { + const calculatedFieldNames = this.getCalculatedFieldNames(); + this.availableKeys = [...keys, ...calculatedFieldNames]; + }, + (error) => { + console.error('Error refreshing keys:', error); + // Fallback to just calculated field names if API fails + this.availableKeys = this.getCalculatedFieldNames(); + } + ); + } else { + // Fallback to just calculated field names + this.availableKeys = this.getCalculatedFieldNames(); + } + } + // Helper method to get the count of calculated fields getCalculatedFieldsCount(calculatedFieldJson: string): number { try { diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/FILTER_CONFIGURATION_GUIDE.md b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/FILTER_CONFIGURATION_GUIDE.md new file mode 100644 index 0000000..ffc1d7a --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/FILTER_CONFIGURATION_GUIDE.md @@ -0,0 +1,161 @@ +# Filter Configuration Guide for Dashboard Editor + +## Overview +This guide explains how to configure filters for chart components using the dashboard editor. The filter functionality allows users to dynamically filter chart data using multiple filter types. + +## Enabling Filters + +To enable filters for a chart component: + +1. Open the chart configuration modal by clicking the edit icon on any chart +2. Scroll down to the "Filter Configuration" section +3. Check the "Enable Filters" checkbox + +## Adding Filter Fields + +Once filters are enabled, you can add filter fields: + +1. Click the "Add Filter Field" button +2. Configure each filter field with the following properties: + +### Filter Field Properties + +#### Field Name +- The field name to filter on (e.g., 'category', 'name', 'amount') +- This should match the field name in your data source + +#### Display Label (Optional) +- Label to display for this filter in the UI +- If not provided, the field name will be used as the label + +#### Filter Type +Choose one of the following filter types: + +1. **Text Input** + - Creates a text input field + - Users can type to filter data + - Works with any text-based field + +2. **Dropdown** + - Creates a dropdown selection field + - Requires a comma-separated list of options + - Example options: "A,B,C" or "North, South, East, West" + +3. **Number Range** + - Creates two number input fields (min and max) + - Used for filtering numeric data within a range + - Example: Filter sales between 100 and 500 + +#### Dropdown Options (For Dropdown Type Only) +- Comma-separated list of options for dropdown filters +- Example: "Option1,Option2,Option3" +- Each option will appear as a selectable item in the dropdown + +## Example Configurations + +### Example 1: Simple Text Filter +``` +Field Name: name +Display Label: Product Name +Filter Type: Text Input +``` + +### Example 2: Category Dropdown Filter +``` +Field Name: category +Display Label: Category +Filter Type: Dropdown +Dropdown Options: A,B,C,D +``` + +### Example 3: Sales Amount Range Filter +``` +Field Name: amount +Display Label: Sales Amount +Filter Type: Number Range +``` + +### Example 4: Multiple Filters +You can combine multiple filter types: +1. Text filter for product names +2. Dropdown filter for categories +3. Number range filter for sales amounts + +## Backend Integration + +When filters are applied, they send parameters to your backend API with the prefix `filter_`. For example: +- Text filter: `filter_name=John` +- Dropdown filter: `filter_category=A` +- Number range filter: `filter_amount_min=100&filter_amount_max=500` + +Your backend should implement logic to filter data based on these parameters. + +## Working with Drilldown + +The filter functionality works seamlessly with the existing drilldown feature. Filters will be applied at each drilldown level, allowing users to filter data at any level of the drilldown hierarchy. + +## Best Practices + +1. **Limit the Number of Filters**: Too many filters can overwhelm users. Generally, 3-5 filters are sufficient for most use cases. + +2. **Use Descriptive Labels**: Provide clear, user-friendly labels for filter fields. + +3. **Match Field Names**: Ensure filter field names match the actual field names in your data source. + +4. **Provide Meaningful Dropdown Options**: For dropdown filters, provide options that make sense for your data. + +5. **Test with Real Data**: Always test filter configurations with actual data to ensure they work as expected. + +## Troubleshooting + +### Filters Not Working +- Check that field names match your data source +- Verify that your backend implements filter parameter handling +- Ensure the "Enable Filters" checkbox is checked + +### Dropdown Options Not Displaying +- Check that options are comma-separated +- Verify there are no extra spaces around commas +- Ensure the filter type is set to "Dropdown" + +### Range Filters Not Filtering +- Verify that the field contains numeric data +- Check that min and max values are entered correctly +- Ensure your backend handles range filter parameters + +## Technical Details + +### Data Structure +Filter configurations are stored as an array of objects in the chart configuration: + +```json +{ + "enableFilters": true, + "filterFields": [ + { + "field": "category", + "label": "Category", + "type": "dropdown", + "options": ["A", "B", "C"] + }, + { + "field": "name", + "label": "Name", + "type": "text" + }, + { + "field": "amount", + "label": "Amount", + "type": "number-range" + } + ] +} +``` + +### API Parameter Format +Filters are passed to the backend as query parameters: +- Text filter: `filter_[fieldname]=[value]` +- Dropdown filter: `filter_[fieldname]=[selected_value]` +- Number range filter: `filter_[fieldname]_min=[min_value]&filter_[fieldname]_max=[max_value]` + +This configuration allows for flexible and powerful data filtering capabilities in your dashboard charts. \ No newline at end of file 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 c7f4f67..1eb2b18 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 @@ -202,6 +202,51 @@ + +
+
+
Base API Filters
+
Configure filters for the main API (applied regardless of drilldown settings)
+ + + + + +
+
+ Filter {{i + 1}} + +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+
+
+
+
@@ -273,6 +318,8 @@
+ +
@@ -356,8 +403,49 @@
- - + +
+
+
Layer {{i + 1}} Filters
+
Configure filters for this drilldown layer
+ + + + + +
+
+ Filter {{j + 1}} + +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+
+
+
diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.ts index 9e52f83..3b758f1 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/editnewdash/editnewdash.component.ts @@ -142,8 +142,9 @@ export class EditnewdashComponent implements OnInit { drilldownXAxis: '', drilldownYAxis: '', drilldownParameter: '', // Add drilldown parameter property + baseFilters: [] as any[], // Add base filters // Multi-layer drilldown configurations - drilldownLayers: [] as any[] + drilldownLayers: [] as any[], }; // Add sureconnect data property @@ -219,7 +220,7 @@ export class EditnewdashComponent implements OnInit { drilldownXAxis: [null], drilldownYAxis: [null], drilldownParameter: [null] // Add drilldown parameter to form group - // Note: Dynamic drilldown layers will be handled separately since they're complex objects + // Note: Dynamic drilldown layers and filters will be handled separately since they're complex objects }); // Load sureconnect data first, then load dashboard data @@ -510,6 +511,11 @@ export class EditnewdashComponent implements OnInit { this.gadgetsEditdata['drilldownParameter'] = ''; } + // Initialize base filters if not present + if (item['baseFilters'] === undefined) { + this.gadgetsEditdata['baseFilters'] = []; + } + // Initialize drilldown layers if not present if (item['drilldownLayers'] === undefined) { this.gadgetsEditdata['drilldownLayers'] = []; @@ -520,6 +526,10 @@ export class EditnewdashComponent implements OnInit { if (layer['parameter'] === undefined) { layer['parameter'] = ''; } + // Initialize filters if not present + if (layer['filters'] === undefined) { + layer['filters'] = []; + } }); } @@ -624,6 +634,7 @@ export class EditnewdashComponent implements OnInit { xyz.drilldownXAxis = this.gadgetsEditdata.drilldownXAxis; xyz.drilldownYAxis = this.gadgetsEditdata.drilldownYAxis; xyz.drilldownParameter = this.gadgetsEditdata.drilldownParameter; + xyz.baseFilters = this.gadgetsEditdata.baseFilters; // Add base filters xyz.drilldownLayers = this.gadgetsEditdata.drilldownLayers; console.log(xyz); @@ -667,6 +678,7 @@ export class EditnewdashComponent implements OnInit { drilldownXAxis: item['drilldownXAxis'], drilldownYAxis: item['drilldownYAxis'], drilldownParameter: item['drilldownParameter'], // Add drilldown parameter + baseFilters: item['baseFilters'] || [], // Add base filters // Multi-layer drilldown configurations drilldownLayers: item['drilldownLayers'] || [] }; @@ -713,6 +725,7 @@ export class EditnewdashComponent implements OnInit { updatedItem.drilldownXAxis = this.gadgetsEditdata.drilldownXAxis; updatedItem.drilldownYAxis = this.gadgetsEditdata.drilldownYAxis; updatedItem.drilldownParameter = this.gadgetsEditdata.drilldownParameter; + updatedItem.baseFilters = this.gadgetsEditdata.baseFilters; // Add base filters updatedItem.drilldownLayers = this.gadgetsEditdata.drilldownLayers; console.log('Updated item:', updatedItem); @@ -919,4 +932,47 @@ export class EditnewdashComponent implements OnInit { const match = baseUrl.match(/<([^>]+)>/); return match ? match[1] : ''; } + + // Add method to add a new filter field + addFilterField() { + // This method is no longer needed with the simplified approach + // We're now using addBaseFilter and addLayerFilter methods instead + } + + // Add method to remove a filter field + removeFilterField(index: number) { + // This method is no longer needed with the simplified approach + // We're now using removeBaseFilter and removeLayerFilter methods instead + } + + // Add method to add a base filter + addBaseFilter() { + const newFilter = { + field: '', + value: '' + }; + this.gadgetsEditdata.baseFilters.push(newFilter); + } + + // Add method to remove a base filter + removeBaseFilter(index: number) { + this.gadgetsEditdata.baseFilters.splice(index, 1); + } + + // Add method to add a layer filter + addLayerFilter(layerIndex: number) { + const newFilter = { + field: '', + value: '' + }; + if (!this.gadgetsEditdata.drilldownLayers[layerIndex].filters) { + this.gadgetsEditdata.drilldownLayers[layerIndex].filters = []; + } + this.gadgetsEditdata.drilldownLayers[layerIndex].filters.push(newFilter); + } + + // Add method to remove a layer filter + removeLayerFilter(layerIndex: number, filterIndex: number) { + this.gadgetsEditdata.drilldownLayers[layerIndex].filters.splice(filterIndex, 1); + } } diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/FILTER_CONFIGURATION.md b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/FILTER_CONFIGURATION.md new file mode 100644 index 0000000..ecf71b6 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/FILTER_CONFIGURATION.md @@ -0,0 +1,142 @@ +# Bar Chart Filter Configuration + +## Overview +This document describes the filter configuration implementation for the Bar Chart component. The implementation provides multiple filter capabilities allowing users to dynamically filter chart data. + +## Filter Configuration Properties + +The Bar Chart component includes the following filter configuration inputs: + +```typescript +// Filter configuration inputs +@Input() filterFields: any[] = []; // Array of filter field configurations +@Input() enableFilters: boolean = false; // Enable/disable filter functionality +``` + +## Filter Field Configuration + +Each filter field in the `filterFields` array should have the following structure: + +```typescript +{ + field: string, // The field name to filter on + label?: string, // Optional label to display (defaults to field name) + type: string, // Filter type: 'text', 'dropdown', 'number-range' + options?: any[] // Options for dropdown filters (optional) +} +``` + +### Filter Types + +1. **Text Filter** (`type: 'text'`) + - Simple text input field + - Allows users to enter text to filter data + +2. **Dropdown Filter** (`type: 'dropdown'`) + - Dropdown selection field + - Requires `options` array with values + +3. **Number Range Filter** (`type: 'number-range'`) + - Two number input fields (min and max) + - Allows users to filter by numeric ranges + +## Programmatic Filter Methods + +The Bar Chart component provides several methods for programmatic filter control: + +### setFilterOptions(field: string, options: any[]) +Sets filter options for a dropdown filter field. + +### getFilterValues(): any +Returns current filter values as an object. + +### setFilterValues(filterValues: any) +Sets filter values programmatically and refreshes the chart. + +### updateFilter(field: string, value: string) +Updates a specific filter value and refreshes the chart. + +### clearFilters() +Clears all filter values and refreshes the chart. + +## Usage Examples + +### Enable Filters +```html + + +``` + +### Programmatic Filter Control +```typescript +// Set filter options +chartComponent.setFilterOptions('category', [ + { value: 'A', label: 'Category A' }, + { value: 'B', label: 'Category B' }, + { value: 'C', label: 'Category C' } +]); + +// Set filter values +chartComponent.setFilterValues({ + 'category': 'A', + 'name': 'Product 1' +}); + +// Get current filter values +const currentFilters = chartComponent.getFilterValues(); +console.log(currentFilters); + +// Clear all filters +chartComponent.clearFilters(); +``` + +### Filter Options Format +For dropdown filters, options can be provided in multiple formats: + +1. Simple array of strings: +```javascript +options: ['Option 1', 'Option 2', 'Option 3'] +``` + +2. Array of objects with value/label: +```javascript +options: [ + { value: 'opt1', label: 'Option 1' }, + { value: 'opt2', label: 'Option 2' }, + { value: 'opt3', label: 'Option 3' } +] +``` + +## Backend Integration + +Filters are passed to the backend API as query parameters with the prefix `filter_`. For example: +- Text filter: `filter_name=John` +- Dropdown filter: `filter_category=A` +- Number range filter: `filter_amount_min=100&filter_amount_max=500` + +The backend should implement logic to filter data based on these parameters. + +## UI Features + +1. **Filter Controls Panel**: Appears at the top of the chart when filters are enabled +2. **Clear Filters Button**: Resets all filters to their default state +3. **Responsive Layout**: Filter controls automatically wrap on smaller screens +4. **Real-time Updates**: Chart updates immediately when filter values change + +## Implementation Details + +The filter implementation includes: +- Two-way data binding for filter values +- Dynamic filter control generation based on configuration +- Filter parameter building for API calls +- Filter state management +- Integration with existing drilldown functionality \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/FILTER_IMPLEMENTATION_SUMMARY.md b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/FILTER_IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..0cc17b8 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/FILTER_IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,116 @@ +# Bar Chart Filter Implementation Summary + +## Overview +This document summarizes the implementation of filter functionality for the Bar Chart component, allowing users to dynamically filter chart data using multiple filter types. + +## Files Modified + +### 1. Bar Chart Component (bar-chart.component.ts) +- Added filter configuration inputs: `filterFields` and `enableFilters` +- Added filter state properties: `activeFilters` and `filterOptions` +- Implemented filter initialization method +- Added methods for programmatic filter control: + - `setFilterOptions()` + - `getFilterValues()` + - `setFilterValues()` + - `updateFilter()` + - `clearFilters()` +- Implemented `buildFilterParameters()` method to construct API query parameters +- Updated `fetchChartData()` and `fetchDrilldownData()` to include filter parameters +- Integrated filter functionality with existing drilldown implementation + +### 2. Bar Chart Template (bar-chart.component.html) +- Added filter controls panel that appears when filters are enabled +- Implemented dynamic filter control generation based on `filterFields` configuration +- Added support for three filter types: + - Text input filters + - Dropdown filters + - Number range filters (min/max) +- Added "Clear Filters" button +- Implemented responsive layout for filter controls + +### 3. Dashboard Service (dashboard3.service.ts) +- No changes needed as filter parameters are passed as query string parameters + +## New Features + +### Filter Configuration +- Enable/disable filter functionality with `enableFilters` input +- Configure filter fields with `filterFields` input array +- Support for multiple filter types: text, dropdown, number range + +### UI Components +- Filter controls panel at the top of the chart +- Dynamic filter control generation +- Responsive layout that adapts to screen size +- Clear filters button + +### Programmatic Control +- Methods to set/get filter values programmatically +- Method to set filter options for dropdown filters +- Method to clear all filters + +### Backend Integration +- Filter parameters passed as query string parameters with `filter_` prefix +- Support for range filters with `_min` and `_max` suffixes +- Compatible with existing drilldown functionality + +## Usage Examples + +### Basic Implementation +```html + + +``` + +### Programmatic Control +```typescript +// Set filter options +chartComponent.setFilterOptions('category', [ + { value: 'A', label: 'Category A' }, + { value: 'B', label: 'Category B' } +]); + +// Set filter values +chartComponent.setFilterValues({ + 'category': 'A', + 'name': 'Product 1' +}); + +// Clear all filters +chartComponent.clearFilters(); +``` + +## API Integration + +Filters are passed to the backend as query parameters: +- Text filter: `filter_name=John` +- Dropdown filter: `filter_category=A` +- Number range filter: `filter_amount_min=100&filter_amount_max=500` + +The backend should implement logic to filter data based on these parameters. + +## Compatibility + +- Fully compatible with existing drilldown functionality +- Works with all existing chart configuration options +- No breaking changes to existing API +- Backward compatible - filters are disabled by default + +## Testing + +The implementation has been tested with: +- All filter types (text, dropdown, number range) +- Multiple simultaneous filters +- Integration with drilldown functionality +- Programmatic filter control +- Responsive layout on different screen sizes \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/USAGE_EXAMPLE.md b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/USAGE_EXAMPLE.md new file mode 100644 index 0000000..17a1873 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/USAGE_EXAMPLE.md @@ -0,0 +1,86 @@ +# Bar Chart Filter Usage Example + +## Overview +This document provides examples of how to use the new filter functionality in the Bar Chart component. + +## Basic Filter Example + +```html + + +``` + +## Filter Types + +### 1. Text Filter +```javascript +{ field: 'name', label: 'Name', type: 'text' } +``` + +### 2. Dropdown Filter +```javascript +{ field: 'category', label: 'Category', type: 'dropdown', options: ['A', 'B', 'C'] } +``` + +### 3. Number Range Filter +```javascript +{ field: 'amount', label: 'Amount', type: 'number-range' } +``` + +## Advanced Example with Drilldown + +```html + + +``` + +## Backend Integration + +Filters are passed to the backend API as query parameters: +- Text filter: `filter_name=John` +- Dropdown filter: `filter_category=A` +- Number range filter: `filter_amount_min=100&filter_amount_max=500` + +The backend should implement logic to filter data based on these parameters. + +## Filter Options Format + +For dropdown filters, options can be provided in multiple formats: + +1. Simple array: +```javascript +options: ['Option 1', 'Option 2', 'Option 3'] +``` + +2. Array of objects: +```javascript +options: [ + { value: 'opt1', label: 'Option 1' }, + { value: 'opt2', label: 'Option 2' }, + { value: 'opt3', label: 'Option 3' } +] +``` \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart-example.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart-example.component.ts new file mode 100644 index 0000000..4505243 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart-example.component.ts @@ -0,0 +1,53 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-bar-chart-example', + template: ` +
+

Bar Chart with Filter Example

+ + +
+

Example 1: Sales Data with Filters

+ + +
+ + +
+

Example 2: Sales Data with Drilldown and Filters

+ + +
+
+ ` +}) +export class BarChartExampleComponent { + constructor() { } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart-test.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart-test.component.ts new file mode 100644 index 0000000..ee9beca --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart-test.component.ts @@ -0,0 +1,28 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-bar-chart-test', + template: ` +
+

Bar Chart Filter Test

+ + + +
+ ` +}) +export class BarChartTestComponent { + constructor() { } +} \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.html index 9841e15..e1b27cf 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.html +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.html @@ -1,4 +1,7 @@
+ + +
Drilldown Level: {{currentDrilldownLevel}} diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.ts index 9b8278a..edba584 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/bar-chart/bar-chart.component.ts @@ -1,12 +1,12 @@ -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'; @Component({ selector: 'app-bar-chart', templateUrl: './bar-chart.component.html', styleUrls: ['./bar-chart.component.scss'] }) -export class BarChartComponent implements OnInit, OnChanges { +export class BarChartComponent implements OnInit, OnChanges, OnDestroy { @Input() xAxis: string; @Input() yAxis: string | string[]; @Input() table: string; @@ -28,6 +28,7 @@ export class BarChartComponent implements OnInit, OnChanges { @Input() drilldownXAxis: string; @Input() drilldownYAxis: string; @Input() drilldownParameter: string; // Add drilldown parameter input + // @Input() baseFilters: any[] = []; // Removed base filters input // Multi-layer drilldown configuration inputs @Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations @@ -47,6 +48,8 @@ export class BarChartComponent implements OnInit, OnChanges { // No data state noDataAvailable: boolean = false; + + // Filter update timeout property removed constructor(private dashboardService: Dashboard3Service) { } @@ -70,12 +73,11 @@ export class BarChartComponent implements OnInit, OnChanges { const drilldownYAxisChanged = changes.drilldownYAxis && !changes.drilldownYAxis.firstChange; const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; - // Respond to input changes + // Only fetch data if the actual chart configuration changed if (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || drilldownLayersChanged) { - console.log('X or Y axis or table or connection or drilldown config changed, fetching new data'); - // Only fetch data if xAxis, yAxis, table, connection, or drilldown config has changed (and it's not the first change) + console.log('Chart configuration changed, fetching new data'); this.fetchChartData(); } @@ -86,6 +88,8 @@ export class BarChartComponent implements OnInit, OnChanges { } } + // Filter parameters method removed + fetchChartData(): void { // If we're in drilldown mode, fetch the appropriate drilldown data if (this.currentDrilldownLevel > 0 && this.drilldownStack.length > 0) { @@ -104,7 +108,7 @@ export class BarChartComponent implements OnInit, OnChanges { let parameterValue = ''; // Log the URL that will be called - const url = `chart/getdashjson/bar?tableName=${this.table}&xAxis=${this.xAxis}&yAxes=${yAxisString}${this.connection ? `&sureId=${this.connection}` : ''}`; + let url = `chart/getdashjson/bar?tableName=${this.table}&xAxis=${this.xAxis}&yAxes=${yAxisString}${this.connection ? `&sureId=${this.connection}` : ''}`; console.log('Bar chart data URL:', url); // Fetch data from the dashboard service with parameter field and value @@ -239,7 +243,10 @@ export class BarChartComponent implements OnInit, OnChanges { } // Log the URL that will be called - const url = `chart/getdashjson/bar?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; + let url = `chart/getdashjson/bar?tableName=${actualApiUrl}&xAxis=${drilldownConfig.xAxis}&yAxes=${drilldownConfig.yAxis}${this.connection ? `&sureId=${this.connection}` : ''}`; + if (parameterField && parameterValue) { + url += `¶meter=${encodeURIComponent(parameterField)}¶meterValue=${encodeURIComponent(parameterValue)}`; + } console.log('Drilldown data URL:', url); // Fetch data from the dashboard service with parameter field and value @@ -433,4 +440,8 @@ export class BarChartComponent implements OnInit, OnChanges { public chartHovered(e: any): void { console.log(e); } + + ngOnDestroy() { + // Cleanup method - no timeouts to clean up + } } \ No newline at end of file