import { Component, EventEmitter, inject, Input, OnInit, Output } from '@angular/core'; import { Filter } from '../../interface/filter.interface'; import { FILTER_TYPE } from '../../enum/filter-type.enum'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ToolbarFilterSidebarComponent } from '../toolbar-filter-sidebar/toolbar-filter-sidebar.component'; import { FilterChange, Group, ToolbarFilterAction } from '../../interface'; import { Filter as iconFilter } from 'lucide-angular'; import { SidebarDialog } from '../../interface/sidebar-dialog.interface'; import { BehaviorSubject } from 'rxjs'; import { SidebarInstance } from '../../interface/sidebar-instance.interface'; @Component({ selector: 'kit-toolbar-filter', templateUrl: './toolbar-filter.component.html', }) export class ToolbarFilterComponent implements OnInit{ @Input() public groups!:Group[] @Output() valueChange: EventEmitter = new EventEmitter(); @Output() actionFilter: EventEmitter = new EventEmitter(); public filters$ = new BehaviorSubject([]); public iconFilter = iconFilter; public filtersToComponents:Filter[] = []; public FILTER_TYPE = FILTER_TYPE; public singleFilterForm: FormGroup = new FormGroup({}); public filtersCount: number = 0 public groupIdPanelOpen!:number; public groupFilterForm: any = {}; private _filters :Filter[] = []; private fb = inject(FormBuilder); private isFilterGroup:boolean = false private previousFilterForm!:any; private previousGroupFilterForm!:any; private INDEX_GROUP_MAIN = 99 private groupsIds!:number[]; private isFilterAdded:boolean = false; constructor(private dialog: MatDialog) {} @Input() public set filters(filters:Filter[]){ this._filters = [...filters]; this.filters$.next(this._filters); if( filters.find(e=>e.group) ){ if(this.groups){ this.updateGroupFilterForm() this.setGroupFiltersCount(); } }else{ this.updateSingleFilterForm() this.setSingleFiltersCount(); } } public get filters(){ return this._filters; } public ngOnInit(): void { this.isFilterGroup = this.groups.length > 0 this.createForm(); if (this.isFilterGroup) { this.setGroupFiltersCount(); } else { this.setSingleFiltersCount(); } } public showFilterButton(){ let show = false; if(this.filters.length > 0){ const findFilter = this.filters.find( e => !e.main); show = findFilter ? true : false; } return show } public setGroupFiltersCount(){ let count = 0; if (!this.groupIdPanelOpen || this.groupIdPanelOpen === 0) { for (const filter of this.filters) { if (filter.group !== undefined && this.groupFilterForm[filter.group]) { const formControl = this.groupFilterForm[filter.group].controls[filter.id]; if (formControl) { const value = formControl.value; count = (value && value !== '' && !filter.main) ? count + 1 : count; } } } } else { for (const filter of this.filters) { if(filter.group === this.groupIdPanelOpen){ const value = this.groupFilterForm[this.groupIdPanelOpen].controls[filter.id].value count = (value && value !== '' && !filter.main) ? count+1 : count } } } this.filtersCount = count; } public setSingleFiltersCount(){ let count = 0; for (const filter of this.filters) { if(this.singleFilterForm.controls[filter.id]) { const value = this.singleFilterForm.controls[filter.id].value count = (value && value !== '' && !filter.main) ? count+1 : count } } this.filtersCount = count } public onAction() { this.openVersionHistoryDialog(); } public openVersionHistoryDialog() { const dialogRef = this.dialog.open(ToolbarFilterSidebarComponent, { data: { filters$: this.filters$, filterForm:this.isFilterGroup ? this.groupFilterForm : this.singleFilterForm, groups:this.groups, filtersCount:this.filtersCount, groupIdPanelOpen:this.groupIdPanelOpen }, panelClass:'toolbar-filter-sidebar', autoFocus: false, position:{top:'5vh',right:'5vh', bottom:'5vh'}, height:'90vh', width:'300px', }) dialogRef.afterClosed().subscribe((sidebarDialog:SidebarDialog) => { if (sidebarDialog && sidebarDialog?.groupId) { this.groupIdPanelOpen = sidebarDialog.groupId; this.setGroupFiltersCount() this.resetGroupFilterFormWhitoutOpenPanel() this.actionFilter.emit({searchGroup:sidebarDialog.groupId}) this.isFilterAdded = true; }else if(!this.isFilterGroup && this.emptySingleFormValues() && sidebarDialog?.filter) { this.groupIdPanelOpen = 0; this.setSingleFiltersCount(); this.actionFilter.emit({search:true}); this.isFilterAdded = true; } else if (!this.isFilterGroup && sidebarDialog?.filter) { this.groupIdPanelOpen = 0; this.setSingleFiltersCount(); this.actionFilter.emit({ search: true }); this.isFilterAdded = true; }else { if((!sidebarDialog || sidebarDialog?.filter === false) && !this.isFilterAdded) { this.filtersCount = 0; if (this.isFilterGroup) { this.resetGroupFilterFormWhitoutOpenPanel(); } else { this.resetSingleFilterForm(); } } if (this.isFilterGroup) { this.setGroupFiltersCount(); } else { this.setSingleFiltersCount(); } this.groupIdPanelOpen = 0; } }); const instance = dialogRef.componentInstance; instance.resetFilterForm$.subscribe((sidebarInstance:SidebarInstance) => { if(!sidebarInstance.groupId){ this.resetSingleFilterForm(); }else{ this.resetGroupFilterForm(sidebarInstance.groupId); } if(sidebarInstance?.emitEvent){ this.isFilterAdded = false; this.actionFilter.emit({clear:true}) } }); } public resetGroupFilterFormWhitoutOpenPanel(){ for(const groupId of this.groupsIds){ if(this.groupIdPanelOpen !== groupId){ this.resetGroupFilterForm(groupId) } } } public resetSingleFilterForm(){ this.singleFilterForm.reset(); this.previousFilterForm = this.singleFilterForm.value; this.setSingleFiltersCount(); } public resetGroupFilterForm(groupId:number){ this.groupFilterForm[groupId].reset(); this.previousGroupFilterForm[groupId] = this.groupFilterForm[groupId].value; this.setGroupFiltersCount(); } public getFilterForm(filter:Filter){ return this.isFilterGroup ? this.groupFilterForm[this.INDEX_GROUP_MAIN].get(filter.id) as FormControl : this.singleFilterForm.get(filter.id) as FormControl; } public getFilter(filter:Filter){ return {...filter} } private emptySingleFormValues(){ const formControlsID = this.filters.reduce((acc:any,filter:any)=> { if (!filter.main) { acc.push(filter.id); } return acc; },[]) const enabledControls = formControlsID.filter( (controlId:any) => !this.singleFilterForm.controls[controlId].disabled ); const emptyControls = enabledControls.filter( (controlId:any) => ( !this.singleFilterForm.controls[controlId].value )) return emptyControls.length === enabledControls.length } private createForm() { if(this.isFilterGroup){ this.createGroupForm(); }else{ this.createSingleForm(); } } private createSingleForm(){ this.singleFilterForm = this.fb.group({}); this.updateSingleFilterForm(); this.singleFilterFormSubscribes(); this.previousFilterForm = this.singleFilterForm.value; } private createGroupForm(){ this.groupsIds = this.groups.map(item=>item.id) if(this.filters.find(e => e.main)){ this.groupsIds = [...this.groupsIds,this.INDEX_GROUP_MAIN] } for (const groupId of this.groupsIds) { this.groupFilterForm = { ...this.groupFilterForm, [groupId]:this.fb.group({}) }; let filters = [] if(groupId === this.INDEX_GROUP_MAIN){ filters = this.filters.filter(e => e.main); }else{ filters = this.filters.filter(e => e.group === groupId); } for(const filter of filters){ if(filter.group === groupId || (filter.main && groupId === this.INDEX_GROUP_MAIN) ){ this.groupFilterForm[groupId].addControl( filter.id, this.fb.control( { value: filter.value ?? '', disabled: filter.disabled ?? false }, filter.validators ) ); } } this.previousGroupFilterForm= { ...this.previousGroupFilterForm, [groupId]:this.groupFilterForm[groupId].value } } this.groupFilterFormSubscribes() } private updateGroupFilterForm() { for (const groupId of this.groupsIds) { const formGroup = this.groupFilterForm[groupId] const filters = this.filters.filter(e => e.group === groupId); for(const filter of filters){ const formControl = formGroup.controls[filter.id] if(filter.disabled){ formControl.disable(); }else{ formControl.enable(); } if(filter?.validators !== undefined){ formControl.clearValidators(); formControl.addValidators(filter.validators); formControl.updateValueAndValidity(); } formControl.updateValueAndValidity(); } } this.setGroupFiltersCount() } private updateSingleFilterForm() { for (const filter of this.filters) { if(this.singleFilterForm.controls[filter.id]){ this.updateFilterFormControl(filter); }else{ this.addFilterFormControl(filter); } } } private updateFilterFormControl(filter:Filter){ const formControl = this.singleFilterForm.controls[filter.id] if(filter.disabled){ formControl.disable(); }else{ formControl.enable(); } if(filter?.validators !== undefined){ formControl.clearValidators(); formControl.addValidators(filter.validators); formControl.updateValueAndValidity(); } formControl.updateValueAndValidity(); } private addFilterFormControl(filter:Filter){ this.singleFilterForm.addControl( filter.id, this.fb.control( { value: filter.value ?? '', disabled: filter.disabled ?? false }, filter.validators ) ); } private singleFilterFormSubscribes(){ this.singleFilterForm.valueChanges.subscribe((filterForm) => { const changedControl = Object.keys(filterForm).find(key => filterForm[key] !== this.previousFilterForm[key]); if (changedControl) { const filterChange:FilterChange = {id:changedControl,value:filterForm[changedControl]} this.valueChange.emit(filterChange) } this.previousFilterForm = filterForm; }); } private groupFilterFormSubscribes(){ for (const groupId of this.groupsIds) { this.groupFilterForm[groupId].valueChanges.subscribe((filterForm:any) => { const changedControl = Object.keys(filterForm).find(key => filterForm[key] !== this.previousGroupFilterForm[groupId][key]); if (changedControl) { const filterChange:FilterChange = {id:changedControl,value:filterForm[changedControl]} this.valueChange.emit(filterChange) } this.previousGroupFilterForm[groupId] = filterForm; }); } } }