compact filter

This commit is contained in:
string 2025-10-27 20:36:22 +05:30
parent afc2c1f8a1
commit 2995328ec1
3 changed files with 179 additions and 194 deletions

View File

@ -1,80 +1,73 @@
<!-- Debug: Show all input values -->
<!-- Display Mode - No configuration UI in runner -->
<div class="compact-filter"> <div class="compact-filter">
<div class="filter-header"> <div class="filter-header" (click)="toggleFilter()">
<span class="filter-label" *ngIf="filterLabel">{{ filterLabel }}</span> <span class="filter-label" *ngIf="filterLabel">{{ filterLabel }}</span>
<span class="filter-key" *ngIf="!filterLabel && filterKey">{{ filterKey }}</span> <span class="filter-key" *ngIf="!filterLabel && filterKey">{{ filterKey }}</span>
<span class="filter-type">({{ filterType }})</span> <span class="filter-type">({{ filterType }})</span>
<clr-icon shape="caret down" class="expand-icon" *ngIf="!isExpanded"></clr-icon>
<clr-icon shape="caret up" class="expand-icon" *ngIf="isExpanded"></clr-icon>
</div> </div>
<!-- Debug: Show which filter type is active --> <div class="filter-content" *ngIf="isExpanded">
<div style="background-color: yellow; padding: 5px; margin: 5px;"> <!-- Text Filter -->
Current filter type: {{ filterType }} <div class="filter-control" *ngIf="filterType === 'text'">
<div *ngIf="filterType === 'text'">Showing TEXT filter</div> <input type="text"
<div *ngIf="filterType === 'dropdown'">Showing DROPDOWN filter</div> [(ngModel)]="filterValue"
<div *ngIf="filterType === 'multiselect'">Showing MULTISELECT filter</div> (ngModelChange)="onFilterValueChange($event)"
<div *ngIf="filterType === 'date-range'">Showing DATE-RANGE filter</div> [placeholder]="filterLabel || filterKey"
<div *ngIf="filterType === 'toggle'">Showing TOGGLE filter</div> class="clr-input compact-input">
</div> </div>
<!-- Text Filter --> <!-- Dropdown Filter -->
<div class="filter-control" *ngIf="filterType === 'text'"> <div class="filter-control" *ngIf="filterType === 'dropdown'">
<input type="text" <select [(ngModel)]="filterValue"
[(ngModel)]="filterValue" (ngModelChange)="onFilterValueChange($event)"
(ngModelChange)="onFilterValueChange($event)" class="clr-select compact-select">
[placeholder]="filterLabel || filterKey" <option value="">{{ filterLabel || filterKey }}</option>
class="clr-input compact-input"> <option *ngFor="let option of filterOptions; let i = index" [value]="option">{{ option }}</option>
</div> </select>
</div>
<!-- Dropdown Filter --> <!-- Multi-Select Filter -->
<div class="filter-control" *ngIf="filterType === 'dropdown'"> <div class="filter-control" *ngIf="filterType === 'multiselect'">
<select [(ngModel)]="filterValue" <div class="multiselect-container">
(ngModelChange)="onFilterValueChange($event)" <div class="checkbox-group">
class="clr-select compact-select"> <div *ngFor="let option of filterOptions; let i = index" class="checkbox-item">
<option value="">{{ filterLabel || filterKey }}</option> <input type="checkbox"
<option *ngFor="let option of filterOptions; let i = index" [value]="option">{{ option }}</option> [checked]="isOptionSelected(option)"
</select> (change)="onMultiSelectChange(option, $event)"
</div> [id]="'checkbox-' + filterKey + '-' + i"
class="clr-checkbox">
<!-- Multi-Select Filter --> <label [for]="'checkbox-' + filterKey + '-' + i" class="checkbox-label">{{ option }}</label>
<div class="filter-control" *ngIf="filterType === 'multiselect'"> </div>
<div class="multiselect-container">
<div class="checkbox-group">
<div *ngFor="let option of filterOptions; let i = index" class="checkbox-item">
<input type="checkbox"
[checked]="isOptionSelected(option)"
(change)="onMultiSelectChange(option, $event)"
[id]="'checkbox-' + filterKey + '-' + i"
class="clr-checkbox">
<label [for]="'checkbox-' + filterKey + '-' + i" class="checkbox-label">{{ option }}</label>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Date Range Filter --> <!-- Date Range Filter -->
<div class="filter-control date-range" *ngIf="filterType === 'date-range'"> <div class="filter-control date-range" *ngIf="filterType === 'date-range'">
<input type="date" <div class="date-input-group">
[(ngModel)]="filterValue.start" <input type="date"
(ngModelChange)="onDateRangeChange({ start: $event, end: filterValue.end })" [(ngModel)]="filterValue.start"
placeholder="Start Date" (ngModelChange)="onDateRangeChange({ start: $event, end: filterValue.end })"
class="clr-input compact-date"> placeholder="Start Date"
<input type="date" class="clr-input compact-date">
[(ngModel)]="filterValue.end" <span class="date-separator">to</span>
(ngModelChange)="onDateRangeChange({ start: filterValue.start, end: $event })" <input type="date"
placeholder="End Date" [(ngModel)]="filterValue.end"
class="clr-input compact-date"> (ngModelChange)="onDateRangeChange({ start: filterValue.start, end: $event })"
</div> placeholder="End Date"
class="clr-input compact-date">
</div>
</div>
<!-- Toggle Filter --> <!-- Toggle Filter -->
<div class="filter-control toggle" *ngIf="filterType === 'toggle'"> <div class="filter-control toggle" *ngIf="filterType === 'toggle'">
<input type="checkbox" <input type="checkbox"
[(ngModel)]="filterValue" [(ngModel)]="filterValue"
(ngModelChange)="onToggleChange($event)" (ngModelChange)="onToggleChange($event)"
clrToggle clrToggle
class="clr-toggle"> class="clr-toggle">
<label class="toggle-label">{{ filterLabel || filterKey }}</label> <label class="toggle-label">{{ filterLabel || filterKey }}</label>
</div>
</div> </div>
</div> </div>

View File

@ -1,148 +1,149 @@
// Make sure the component is visible with very obvious styling
.compact-filter { .compact-filter {
display: block !important; display: block;
min-width: 200px !important; min-width: 200px;
max-width: 300px !important; max-width: 300px;
margin: 10px !important; margin: 8px;
padding: 15px !important; padding: 0;
background: #e3f2fd !important; // Light blue background background: #ffffff;
border: 3px solid #1976d2 !important; // Dark blue border border: 1px solid #d7d7d7;
border-radius: 8px !important; border-radius: 4px;
font-size: 14px !important; font-size: 14px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
.filter-header { .filter-header {
display: flex !important; display: flex;
justify-content: space-between !important; justify-content: space-between;
align-items: center !important; align-items: center;
margin-bottom: 10px !important; padding: 12px 15px;
padding: 5px !important; cursor: pointer;
background: #bbdefb !important; // Lighter blue header background: #f8f8f8;
border-radius: 4px !important; border-bottom: 1px solid #eaeaea;
border-radius: 4px 4px 0 0;
&:hover {
background: #f0f0f0;
}
.filter-label, .filter-key { .filter-label, .filter-key {
font-weight: bold !important; font-weight: 500;
white-space: nowrap !important; color: #333333;
overflow: hidden !important; flex-grow: 1;
text-overflow: ellipsis !important;
flex-grow: 1 !important;
color: #0d47a1 !important; // Dark blue text
} }
.filter-type { .filter-type {
font-size: 12px !important; font-size: 12px;
color: #424242 !important; color: #666666;
margin-left: 8px !important; margin: 0 8px;
background: #fff !important; background: #eaeaea;
padding: 2px 6px !important; padding: 2px 8px;
border-radius: 10px !important; border-radius: 12px;
}
.expand-icon {
width: 16px;
height: 16px;
color: #666666;
} }
} }
.filter-control { .filter-content {
display: block !important; padding: 15px;
margin: 8px 0 !important;
padding: 8px !important;
background: #f5f5f5 !important;
border-radius: 4px !important;
&.date-range { .filter-control {
display: flex !important; margin-bottom: 12px;
flex-direction: column !important;
gap: 5px !important; &:last-child {
} margin-bottom: 0;
}
&.toggle {
display: flex !important; &.date-range {
align-items: center !important; .date-input-group {
justify-content: flex-start !important; display: flex;
gap: 8px !important; align-items: center;
gap: 8px;
.date-separator {
font-size: 14px;
color: #666666;
}
}
}
&.toggle {
display: flex;
align-items: center;
gap: 8px;
}
} }
} }
.compact-input, .compact-input,
.compact-select, .compact-select,
.compact-multiselect,
.compact-date { .compact-date {
width: 100% !important; width: 100%;
padding: 8px 12px !important; padding: 8px 12px;
font-size: 14px !important; font-size: 14px;
border-radius: 4px !important; border: 1px solid #d7d7d7;
min-height: 36px !important; border-radius: 4px;
border: 2px solid #4caf50 !important; // Green border background: #ffffff;
background: #fff !important;
}
.compact-select {
height: 36px !important;
}
.multiselect-container {
max-height: 200px !important;
overflow-y: auto !important;
border: 2px solid #ff9800 !important; // Orange border
border-radius: 4px !important;
padding: 10px !important;
background: #fff8e1 !important; // Light yellow background
}
.checkbox-group {
display: flex !important;
flex-direction: column !important;
gap: 8px !important;
}
.checkbox-item {
display: flex !important;
align-items: center !important;
gap: 8px !important;
padding: 5px !important;
border-radius: 4px !important;
&:hover { &:focus {
background: #f0f0f0 !important; outline: none;
border-color: #0072ce;
box-shadow: 0 0 0 1px #0072ce;
} }
} }
.checkbox-label { .compact-select {
font-size: 14px !important; height: 36px;
margin: 0 !important;
cursor: pointer !important;
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
color: #333 !important;
} }
.clr-checkbox { .multiselect-container {
margin: 0 !important; max-height: 200px;
cursor: pointer !important; overflow-y: auto;
width: 18px !important; border: 1px solid #d7d7d7;
height: 18px !important; border-radius: 4px;
padding: 10px;
background: #ffffff;
}
.checkbox-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.checkbox-item {
display: flex;
align-items: center;
gap: 8px;
.clr-checkbox {
width: 16px;
height: 16px;
cursor: pointer;
}
.checkbox-label {
font-size: 14px;
margin: 0;
cursor: pointer;
color: #333333;
}
} }
.toggle-label { .toggle-label {
margin: 0 !important; margin: 0;
font-size: 14px !important; font-size: 14px;
white-space: nowrap !important; color: #333333;
overflow: hidden !important;
text-overflow: ellipsis !important;
max-width: 200px !important;
color: #333 !important;
} }
.clr-toggle { .clr-toggle {
margin: 0 8px 0 0 !important; margin: 0;
width: 40px !important;
height: 20px !important;
} }
} }
// Add a very obvious background to make sure the component is visible // Host styling
:host { :host {
display: block !important; display: block;
background-color: #fffde7 !important; // Very light yellow
padding: 15px !important;
margin: 15px !important;
border: 4px solid #f57f17 !important; // Orange border
border-radius: 10px !important;
} }

View File

@ -20,6 +20,7 @@ export class CompactFilterRunnerComponent implements OnInit, OnChanges {
availableFilters: Filter[] = []; availableFilters: Filter[] = [];
availableKeys: string[] = []; availableKeys: string[] = [];
availableValues: string[] = []; availableValues: string[] = [];
isExpanded: boolean = false; // Add expansion state
constructor( constructor(
private filterService: FilterService private filterService: FilterService
@ -70,6 +71,11 @@ export class CompactFilterRunnerComponent implements OnInit, OnChanges {
console.log('=========================================='); console.log('==========================================');
} }
// Toggle filter expansion
toggleFilter(): void {
this.isExpanded = !this.isExpanded;
}
// Register this filter with the filter service // Register this filter with the filter service
registerFilter(): void { registerFilter(): void {
console.log('Registering filter with key:', this.filterKey, 'type:', this.filterType); console.log('Registering filter with key:', this.filterKey, 'type:', this.filterType);
@ -198,14 +204,8 @@ export class CompactFilterRunnerComponent implements OnInit, OnChanges {
this.onFilterValueChange(dateRange); this.onFilterValueChange(dateRange);
} }
// Handle multi-select changes // Handle multi-select changes
onMultiSelectChange(option: string, event: any): void { onMultiSelectChange(option: string, event: any): void {
console.log('=== MULTISELECT CHANGE DEBUG ===');
console.log('Option:', option);
console.log('Event:', event);
console.log('Checked:', event.target.checked);
const checked = event.target.checked; const checked = event.target.checked;
// Initialize filterValue as array if it's not already // Initialize filterValue as array if it's not already
@ -217,38 +217,29 @@ export class CompactFilterRunnerComponent implements OnInit, OnChanges {
// Add option to array if not already present // Add option to array if not already present
if (!this.filterValue.includes(option)) { if (!this.filterValue.includes(option)) {
this.filterValue.push(option); this.filterValue.push(option);
console.log('Added option to filter value:', option);
} }
} else { } else {
// Remove option from array // Remove option from array
this.filterValue = this.filterValue.filter((item: string) => item !== option); this.filterValue = this.filterValue.filter((item: string) => item !== option);
console.log('Removed option from filter value:', option);
} }
console.log('Updated filter value:', this.filterValue);
// Emit the change // Emit the change
this.onFilterValueChange(this.filterValue); this.onFilterValueChange(this.filterValue);
console.log('==============================');
} }
// Add method to check if an option is selected for checkboxes (needed for proper UI rendering) // Add method to check if an option is selected for checkboxes (needed for proper UI rendering)
isOptionSelected(option: string): boolean { isOptionSelected(option: string): boolean {
console.log('Checking if option is selected:', option, 'Current filter value:', this.filterValue); console.log('Checking if option is selected:', option, 'Current filter value:', this.filterValue);
if (!this.filterValue) { if (!this.filterValue) {
console.log('No filter value, returning false');
return false; return false;
} }
// Ensure filterValue is an array for multiselect // Ensure filterValue is an array for multiselect
if (!Array.isArray(this.filterValue)) { if (!Array.isArray(this.filterValue)) {
console.log('Filter value is not an array, converting to array');
this.filterValue = []; this.filterValue = [];
return false; return false;
} }
const result = this.filterValue.includes(option); return this.filterValue.includes(option);
console.log('Option', option, 'is selected:', result);
return result;
} }
} }