From 4f82ae8698358453d6eac26e917425a42acb86ad Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Tue, 28 Oct 2025 12:40:01 +0530 Subject: [PATCH] grid view --- .../grid-view/grid-view.component.html | 218 +++++++++++++++ .../grid-view/grid-view.component.scss | 136 ++++++++-- .../gadgets/grid-view/grid-view.component.ts | 255 ++++++++++++++++++ 3 files changed, 593 insertions(+), 16 deletions(-) diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.html b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.html index 293bd06..57ddac8 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.html +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.html @@ -1,5 +1,223 @@
+ +
+ +
+

Base Filters

+
+
+
{{ filter.field }} ({{ filter.type || 'text' }})
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+
+ + +
+
+ + to + +
+
+ + +
+ + +
+
+
+
+ + +
+

Drilldown Filters

+
+
+
{{ filter.field }} ({{ filter.type || 'text' }})
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+
+ + +
+
+ + to + +
+
+ + +
+ + +
+
+
+
+ + +
+

Layer Filters

+
+
+
{{ filter.field }} ({{ filter.type || 'text' }})
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+
+ + +
+
+ + to + +
+
+ + +
+ + +
+
+
+
+ + +
+ +
+
+

{{charttitle || 'Data Grid'}}

diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.scss b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.scss index 4668268..7937ca0 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.scss +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.scss @@ -1,28 +1,132 @@ -// Add styles for drilldown navigation -.alert-info { - background-color: #dcedf7; - border-color: #a3d4f5; - color: #21333b; +.filter-section { + margin-bottom: 20px; + padding: 15px; + border: 1px solid #ddd; + border-radius: 4px; + background-color: #f9f9f9; } -.alert-info .alert-icon { - color: #0072a3; +.filter-group { + margin-bottom: 15px; + + h4 { + margin-top: 0; + margin-bottom: 10px; + color: #333; + font-weight: 600; + } } -.btn-link { - color: #0072a3; - text-decoration: none; +.filter-controls { + display: flex; + flex-wrap: wrap; + gap: 15px; } -.btn-link:hover { - color: #00567a; - text-decoration: underline; +.filter-item { + flex: 1 1 300px; + min-width: 250px; + padding: 10px; + background: white; + border: 1px solid #e0e0e0; + border-radius: 4px; +} + +.filter-label { + font-weight: 500; + margin-bottom: 8px; + color: #555; + font-size: 14px; +} + +.filter-input { + width: 100%; + + .filter-text-input, + .filter-select, + .filter-date { + width: 100%; + padding: 6px 12px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 14px; + } + + .filter-select { + height: 34px; + } +} + +.multiselect-container { + .checkbox-group { + display: flex; + flex-direction: column; + gap: 5px; + } + + .checkbox-item { + display: flex; + align-items: center; + gap: 8px; + + .checkbox-label { + margin: 0; + font-size: 14px; + cursor: pointer; + } + } +} + +.date-range { + .date-input-group { + display: flex; + align-items: center; + gap: 8px; + } + + .date-separator { + margin: 0 5px; + color: #777; + } +} + +.toggle { + display: flex; + align-items: center; + gap: 8px; + + .toggle-label { + margin: 0; + font-size: 14px; + cursor: pointer; + } +} + +.filter-actions { + margin-top: 15px; + padding-top: 15px; + border-top: 1px solid #eee; + + .btn { + font-size: 13px; + } } .dg-wrapper { - padding: 12px; + padding: 15px; } -.clr-row { - margin-bottom: 12px; +clr-datagrid { + margin-top: 10px; +} + +// Responsive design +@media (max-width: 768px) { + .filter-controls { + flex-direction: column; + } + + .filter-item { + min-width: 100%; + } } \ No newline at end of file diff --git a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.ts b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.ts index f51bc2b..278b88e 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/builder/dashboardnew/gadgets/grid-view/grid-view.component.ts @@ -66,6 +66,9 @@ export class GridViewComponent implements OnInit, OnChanges, OnDestroy { // Add subscriptions to unsubscribe on destroy private subscriptions: Subscription[] = []; + // Add a flag to track if filters have been initialized + private filtersInitialized: boolean = false; + constructor( private mainservice: UsergrpmaintainceService, private dashboardService: Dashboard3Service, @@ -102,6 +105,12 @@ export class GridViewComponent implements OnInit, OnChanges, OnDestroy { const drilldownYAxisChanged = changes.drilldownYAxis && !changes.drilldownYAxis.firstChange; const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; + // Initialize filter values if they haven't been initialized yet + if (!this.filtersInitialized && (changes.baseFilters || changes.drilldownFilters || changes.drilldownLayers)) { + this.initializeFilterValues(); + this.filtersInitialized = true; + } + // Respond to input changes if (!this.isFetchingData && (xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || @@ -112,6 +121,84 @@ export class GridViewComponent implements OnInit, OnChanges, OnDestroy { } } + // Initialize filter values with proper default values based on type + private initializeFilterValues(): void { + console.log('Initializing filter values'); + + // Initialize base filters + if (this.baseFilters) { + this.baseFilters.forEach(filter => { + if (filter.value === undefined || filter.value === null) { + switch (filter.type) { + case 'multiselect': + filter.value = []; + break; + case 'date-range': + filter.value = { start: null, end: null }; + break; + case 'toggle': + filter.value = false; + break; + default: + filter.value = ''; + } + } + }); + } + + // Initialize drilldown filters + if (this.drilldownFilters) { + this.drilldownFilters.forEach(filter => { + if (filter.value === undefined || filter.value === null) { + switch (filter.type) { + case 'multiselect': + filter.value = []; + break; + case 'date-range': + filter.value = { start: null, end: null }; + break; + case 'toggle': + filter.value = false; + break; + default: + filter.value = ''; + } + } + }); + } + + // Initialize layer filters + if (this.drilldownLayers) { + this.drilldownLayers.forEach(layer => { + if (layer.filters) { + layer.filters.forEach((filter: any) => { + if (filter.value === undefined || filter.value === null) { + switch (filter.type) { + case 'multiselect': + filter.value = []; + break; + case 'date-range': + filter.value = { start: null, end: null }; + break; + case 'toggle': + filter.value = false; + break; + default: + filter.value = ''; + } + } + }); + } + }); + } + + console.log('Filter values initialized:', { + baseFilters: this.baseFilters, + drilldownFilters: this.drilldownFilters, + drilldownLayers: this.drilldownLayers + }); + } + // Dynamic headers for the grid fetchGridData(): void { @@ -628,6 +715,174 @@ export class GridViewComponent implements OnInit, OnChanges, OnDestroy { .replace(/^./, str => str.toUpperCase()); } + // Check if there are active filters + hasActiveFilters(): boolean { + return (this.baseFilters && this.baseFilters.length > 0) || + (this.drilldownFilters && this.drilldownFilters.length > 0) || + this.hasActiveLayerFilters(); + } + + // Check if there are active layer filters for current drilldown level + hasActiveLayerFilters(): boolean { + if (this.currentDrilldownLevel > 1 && this.drilldownLayers && this.drilldownLayers.length > 0) { + const layerIndex = this.currentDrilldownLevel - 2; // -2 because level 1 is base drilldown + return layerIndex < this.drilldownLayers.length && + this.drilldownLayers[layerIndex].filters && + this.drilldownLayers[layerIndex].filters.length > 0; + } + return false; + } + + // Get active layer filters for current drilldown level + getActiveLayerFilters(): any[] { + if (this.currentDrilldownLevel > 1 && this.drilldownLayers && this.drilldownLayers.length > 0) { + const layerIndex = this.currentDrilldownLevel - 2; // -2 because level 1 is base drilldown + if (layerIndex < this.drilldownLayers.length && + this.drilldownLayers[layerIndex].filters) { + return this.drilldownLayers[layerIndex].filters; + } + } + return []; + } + + // Get filter options for dropdown/multiselect filters + getFilterOptions(filter: any): string[] { + if (filter.options) { + if (Array.isArray(filter.options)) { + return filter.options; + } else if (typeof filter.options === 'string') { + return filter.options.split(',').map(opt => opt.trim()).filter(opt => opt); + } + } + return []; + } + + // Check if an option is selected for multiselect filters + isOptionSelected(filter: any, option: string): boolean { + if (!filter.value) { + return false; + } + + if (Array.isArray(filter.value)) { + return filter.value.includes(option); + } + + return filter.value === option; + } + + // Handle base filter changes + onBaseFilterChange(filter: any): void { + console.log('Base filter changed:', filter); + // Refresh data when filter changes + this.fetchGridData(); + } + + // Handle drilldown filter changes + onDrilldownFilterChange(filter: any): void { + console.log('Drilldown filter changed:', filter); + // Refresh data when filter changes + this.fetchGridData(); + } + + // Handle layer filter changes + onLayerFilterChange(filter: any): void { + console.log('Layer filter changed:', filter); + // Refresh data when filter changes + this.fetchGridData(); + } + + // Handle multiselect changes + onMultiSelectChange(filter: any, option: string, event: any): void { + const checked = event.target.checked; + + // Initialize filter.value as array if it's not already + if (!Array.isArray(filter.value)) { + filter.value = []; + } + + if (checked) { + // Add option to array if not already present + if (!filter.value.includes(option)) { + filter.value.push(option); + } + } else { + // Remove option from array + filter.value = filter.value.filter((item: string) => item !== option); + } + + // Refresh data when filter changes + this.fetchGridData(); + } + + // Handle date range changes + onDateRangeChange(filter: any, dateRange: { start: string | null, end: string | null }): void { + filter.value = dateRange; + // Refresh data when filter changes + this.fetchGridData(); + } + + // Handle toggle changes + onToggleChange(filter: any, checked: boolean): void { + filter.value = checked; + // Refresh data when filter changes + this.fetchGridData(); + } + + // Clear all filters + clearAllFilters(): void { + // Clear base filters + if (this.baseFilters) { + this.baseFilters.forEach(filter => { + if (filter.type === 'multiselect') { + filter.value = []; + } else if (filter.type === 'date-range') { + filter.value = { start: null, end: null }; + } else if (filter.type === 'toggle') { + filter.value = false; + } else { + filter.value = ''; + } + }); + } + + // Clear drilldown filters + if (this.drilldownFilters) { + this.drilldownFilters.forEach(filter => { + if (filter.type === 'multiselect') { + filter.value = []; + } else if (filter.type === 'date-range') { + filter.value = { start: null, end: null }; + } else if (filter.type === 'toggle') { + filter.value = false; + } else { + filter.value = ''; + } + }); + } + + // Clear layer filters + if (this.drilldownLayers) { + this.drilldownLayers.forEach(layer => { + if (layer.filters) { + layer.filters.forEach((filter: any) => { + if (filter.type === 'multiselect') { + filter.value = []; + } else if (filter.type === 'date-range') { + filter.value = { start: null, end: null }; + } else if (filter.type === 'toggle') { + filter.value = false; + } else { + filter.value = ''; + } + }); + } + }); + } + + // Refresh data + this.fetchGridData(); + } + ngOnDestroy() { // Unsubscribe from all subscriptions to prevent memory leaks console.log('GridViewComponent ngOnDestroy called, unsubscribing from', this.subscriptions.length, 'subscriptions');