grid view
This commit is contained in:
		
							parent
							
								
									4f82ae8698
								
							
						
					
					
						commit
						ced99e0940
					
				| @ -28,16 +28,25 @@ | |||||||
|               </select> |               </select> | ||||||
|             </div> |             </div> | ||||||
|              |              | ||||||
|             <!-- Multi-Select Filter --> |             <!-- Multi-Select Filter - Updated to show key first, then dropdown on click --> | ||||||
|             <div *ngIf="filter.type === 'multiselect'" class="filter-input multiselect-container"> |             <div *ngIf="filter.type === 'multiselect'" class="filter-input multiselect-container"> | ||||||
|               <div class="checkbox-group"> |               <div class="multiselect-display" (click)="toggleMultiselect(filter, 'base')"> | ||||||
|                 <div *ngFor="let option of getFilterOptions(filter)" class="checkbox-item"> |                 <span class="multiselect-label">{{ filter.field }}</span> | ||||||
|                   <input type="checkbox"  |                 <span class="multiselect-value" *ngIf="getSelectedOptionsCount(filter) > 0"> | ||||||
|                          [checked]="isOptionSelected(filter, option)"  |                   ({{ getSelectedOptionsCount(filter) }} selected) | ||||||
|                          (change)="onMultiSelectChange(filter, option, $event)" |                 </span> | ||||||
|                          [id]="'base-' + filter.field + '-' + option"  |                 <clr-icon shape="caret down" class="dropdown-icon"></clr-icon> | ||||||
|                          class="clr-checkbox"> |               </div> | ||||||
|                   <label [for]="'base-' + filter.field + '-' + option" class="checkbox-label">{{ option }}</label> |               <div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'base')"> | ||||||
|  |                 <div class="checkbox-group"> | ||||||
|  |                   <div *ngFor="let option of getFilterOptions(filter); let i = index" class="checkbox-item"> | ||||||
|  |                     <input type="checkbox"  | ||||||
|  |                            [checked]="isOptionSelected(filter, option)"  | ||||||
|  |                            (change)="onMultiSelectChange(filter, option, $event)" | ||||||
|  |                            [id]="'base-' + filter.field + '-' + i"  | ||||||
|  |                            class="clr-checkbox"> | ||||||
|  |                     <label [for]="'base-' + filter.field + '-' + i" class="checkbox-label">{{ option }}</label> | ||||||
|  |                   </div> | ||||||
|                 </div> |                 </div> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
| @ -98,16 +107,25 @@ | |||||||
|               </select> |               </select> | ||||||
|             </div> |             </div> | ||||||
|              |              | ||||||
|             <!-- Multi-Select Filter --> |             <!-- Multi-Select Filter - Updated to show key first, then dropdown on click --> | ||||||
|             <div *ngIf="filter.type === 'multiselect'" class="filter-input multiselect-container"> |             <div *ngIf="filter.type === 'multiselect'" class="filter-input multiselect-container"> | ||||||
|               <div class="checkbox-group"> |               <div class="multiselect-display" (click)="toggleMultiselect(filter, 'drilldown')"> | ||||||
|                 <div *ngFor="let option of getFilterOptions(filter)" class="checkbox-item"> |                 <span class="multiselect-label">{{ filter.field }}</span> | ||||||
|                   <input type="checkbox"  |                 <span class="multiselect-value" *ngIf="getSelectedOptionsCount(filter) > 0"> | ||||||
|                          [checked]="isOptionSelected(filter, option)"  |                   ({{ getSelectedOptionsCount(filter) }} selected) | ||||||
|                          (change)="onMultiSelectChange(filter, option, $event)" |                 </span> | ||||||
|                          [id]="'drilldown-' + filter.field + '-' + option"  |                 <clr-icon shape="caret down" class="dropdown-icon"></clr-icon> | ||||||
|                          class="clr-checkbox"> |               </div> | ||||||
|                   <label [for]="'drilldown-' + filter.field + '-' + option" class="checkbox-label">{{ option }}</label> |               <div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'drilldown')"> | ||||||
|  |                 <div class="checkbox-group"> | ||||||
|  |                   <div *ngFor="let option of getFilterOptions(filter); let i = index" class="checkbox-item"> | ||||||
|  |                     <input type="checkbox"  | ||||||
|  |                            [checked]="isOptionSelected(filter, option)"  | ||||||
|  |                            (change)="onMultiSelectChange(filter, option, $event)" | ||||||
|  |                            [id]="'drilldown-' + filter.field + '-' + i"  | ||||||
|  |                            class="clr-checkbox"> | ||||||
|  |                     <label [for]="'drilldown-' + filter.field + '-' + i" class="checkbox-label">{{ option }}</label> | ||||||
|  |                   </div> | ||||||
|                 </div> |                 </div> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
| @ -168,16 +186,25 @@ | |||||||
|               </select> |               </select> | ||||||
|             </div> |             </div> | ||||||
|              |              | ||||||
|             <!-- Multi-Select Filter --> |             <!-- Multi-Select Filter - Updated to show key first, then dropdown on click --> | ||||||
|             <div *ngIf="filter.type === 'multiselect'" class="filter-input multiselect-container"> |             <div *ngIf="filter.type === 'multiselect'" class="filter-input multiselect-container"> | ||||||
|               <div class="checkbox-group"> |               <div class="multiselect-display" (click)="toggleMultiselect(filter, 'layer')"> | ||||||
|                 <div *ngFor="let option of getFilterOptions(filter)" class="checkbox-item"> |                 <span class="multiselect-label">{{ filter.field }}</span> | ||||||
|                   <input type="checkbox"  |                 <span class="multiselect-value" *ngIf="getSelectedOptionsCount(filter) > 0"> | ||||||
|                          [checked]="isOptionSelected(filter, option)"  |                   ({{ getSelectedOptionsCount(filter) }} selected) | ||||||
|                          (change)="onMultiSelectChange(filter, option, $event)" |                 </span> | ||||||
|                          [id]="'layer-' + filter.field + '-' + option"  |                 <clr-icon shape="caret down" class="dropdown-icon"></clr-icon> | ||||||
|                          class="clr-checkbox"> |               </div> | ||||||
|                   <label [for]="'layer-' + filter.field + '-' + option" class="checkbox-label">{{ option }}</label> |               <div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'layer')"> | ||||||
|  |                 <div class="checkbox-group"> | ||||||
|  |                   <div *ngFor="let option of getFilterOptions(filter); let i = index" class="checkbox-item"> | ||||||
|  |                     <input type="checkbox"  | ||||||
|  |                            [checked]="isOptionSelected(filter, option)"  | ||||||
|  |                            (change)="onMultiSelectChange(filter, option, $event)" | ||||||
|  |                            [id]="'layer-' + filter.field + '-' + i"  | ||||||
|  |                            class="clr-checkbox"> | ||||||
|  |                     <label [for]="'layer-' + filter.field + '-' + i" class="checkbox-label">{{ option }}</label> | ||||||
|  |                   </div> | ||||||
|                 </div> |                 </div> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
|  | |||||||
| @ -58,21 +58,69 @@ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .multiselect-container { | .multiselect-container { | ||||||
|   .checkbox-group { |   position: relative; | ||||||
|     display: flex; | } | ||||||
|     flex-direction: column; | 
 | ||||||
|     gap: 5px; | .multiselect-display { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   padding: 6px 12px; | ||||||
|  |   border: 1px solid #ccc; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   background: white; | ||||||
|  |   cursor: pointer; | ||||||
|  |   min-height: 34px; | ||||||
|  |    | ||||||
|  |   .multiselect-label { | ||||||
|  |     flex: 1; | ||||||
|  |     font-size: 14px; | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   .checkbox-item { |   .multiselect-value { | ||||||
|     display: flex; |     color: #666; | ||||||
|     align-items: center; |     font-size: 12px; | ||||||
|     gap: 8px; |     margin-right: 8px; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   .dropdown-icon { | ||||||
|  |     flex-shrink: 0; | ||||||
|  |     transition: transform 0.2s ease; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   &:hover { | ||||||
|  |     border-color: #999; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .multiselect-dropdown { | ||||||
|  |   position: absolute; | ||||||
|  |   top: 100%; | ||||||
|  |   left: 0; | ||||||
|  |   right: 0; | ||||||
|  |   z-index: 1000; | ||||||
|  |   background: white; | ||||||
|  |   border: 1px solid #ccc; | ||||||
|  |   border-top: none; | ||||||
|  |   border-radius: 0 0 4px 4px; | ||||||
|  |   box-shadow: 0 2px 4px rgba(0,0,0,0.1); | ||||||
|  |   max-height: 200px; | ||||||
|  |   overflow-y: auto; | ||||||
|  |    | ||||||
|  |   .checkbox-group { | ||||||
|  |     padding: 8px; | ||||||
|      |      | ||||||
|     .checkbox-label { |     .checkbox-item { | ||||||
|       margin: 0; |       display: flex; | ||||||
|       font-size: 14px; |       align-items: center; | ||||||
|       cursor: pointer; |       gap: 8px; | ||||||
|  |       padding: 4px 0; | ||||||
|  |        | ||||||
|  |       .checkbox-label { | ||||||
|  |         margin: 0; | ||||||
|  |         font-size: 14px; | ||||||
|  |         cursor: pointer; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -69,6 +69,12 @@ export class GridViewComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|   // Add a flag to track if filters have been initialized
 |   // Add a flag to track if filters have been initialized
 | ||||||
|   private filtersInitialized: boolean = false; |   private filtersInitialized: boolean = false; | ||||||
| 
 | 
 | ||||||
|  |   // Add properties to track open multiselect dropdowns
 | ||||||
|  |   private openMultiselects: Map<string, string> = new Map(); // Map of filterId -> context
 | ||||||
|  | 
 | ||||||
|  |   // Add property to track document click handler
 | ||||||
|  |   private documentClickHandler: ((event: MouseEvent) => void) | null = null; | ||||||
|  | 
 | ||||||
|   constructor( |   constructor( | ||||||
|     private mainservice: UsergrpmaintainceService, |     private mainservice: UsergrpmaintainceService, | ||||||
|     private dashboardService: Dashboard3Service, |     private dashboardService: Dashboard3Service, | ||||||
| @ -828,6 +834,67 @@ export class GridViewComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|     this.fetchGridData(); |     this.fetchGridData(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   // Toggle multiselect dropdown visibility
 | ||||||
|  |   toggleMultiselect(filter: any, context: string): void { | ||||||
|  |     const filterId = `${context}-${filter.field}`; | ||||||
|  |     if (this.isMultiselectOpen(filter, context)) { | ||||||
|  |       this.openMultiselects.delete(filterId); | ||||||
|  |     } else { | ||||||
|  |       // Close all other multiselects first
 | ||||||
|  |       this.openMultiselects.clear(); | ||||||
|  |       this.openMultiselects.set(filterId, context); | ||||||
|  |        | ||||||
|  |       // Add document click handler to close dropdown when clicking outside
 | ||||||
|  |       this.addDocumentClickHandler(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Add document click handler to close dropdowns when clicking outside
 | ||||||
|  |   private addDocumentClickHandler(): void { | ||||||
|  |     if (!this.documentClickHandler) { | ||||||
|  |       this.documentClickHandler = (event: MouseEvent) => { | ||||||
|  |         const target = event.target as HTMLElement; | ||||||
|  |         // Check if click is outside any multiselect dropdown
 | ||||||
|  |         if (!target.closest('.multiselect-container')) { | ||||||
|  |           this.openMultiselects.clear(); | ||||||
|  |           this.removeDocumentClickHandler(); | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |        | ||||||
|  |       // Use setTimeout to ensure the click event that opened the dropdown doesn't immediately close it
 | ||||||
|  |       setTimeout(() => { | ||||||
|  |         document.addEventListener('click', this.documentClickHandler!); | ||||||
|  |       }, 0); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Remove document click handler
 | ||||||
|  |   private removeDocumentClickHandler(): void { | ||||||
|  |     if (this.documentClickHandler) { | ||||||
|  |       document.removeEventListener('click', this.documentClickHandler); | ||||||
|  |       this.documentClickHandler = null; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Check if multiselect dropdown is open
 | ||||||
|  |   isMultiselectOpen(filter: any, context: string): boolean { | ||||||
|  |     const filterId = `${context}-${filter.field}`; | ||||||
|  |     return this.openMultiselects.has(filterId); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Get count of selected options for a multiselect filter
 | ||||||
|  |   getSelectedOptionsCount(filter: any): number { | ||||||
|  |     if (!filter.value) { | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     if (Array.isArray(filter.value)) { | ||||||
|  |       return filter.value.length; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   // Clear all filters
 |   // Clear all filters
 | ||||||
|   clearAllFilters(): void { |   clearAllFilters(): void { | ||||||
|     // Clear base filters
 |     // Clear base filters
 | ||||||
| @ -879,6 +946,9 @@ export class GridViewComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     // Close all multiselect dropdowns
 | ||||||
|  |     this.openMultiselects.clear(); | ||||||
|  |      | ||||||
|     // Refresh data
 |     // Refresh data
 | ||||||
|     this.fetchGridData(); |     this.fetchGridData(); | ||||||
|   } |   } | ||||||
| @ -899,6 +969,12 @@ export class GridViewComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|     this.drilldownStack = []; |     this.drilldownStack = []; | ||||||
|     this.originalGridData = []; |     this.originalGridData = []; | ||||||
| 
 | 
 | ||||||
|  |     // Clear multiselect tracking
 | ||||||
|  |     this.openMultiselects.clear(); | ||||||
|  |      | ||||||
|  |     // Remove document click handler
 | ||||||
|  |     this.removeDocumentClickHandler(); | ||||||
|  |      | ||||||
|     console.log('GridViewComponent destroyed and cleaned up'); |     console.log('GridViewComponent destroyed and cleaned up'); | ||||||
|   } |   } | ||||||
| } | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user