LP#1846042: take advantage of ngbDropdown container="body"
[Evergreen.git] / Open-ILS / src / eg2 / src / app / share / grid / grid-filter-control.component.html
1
2 <!-- drop-down toggle link -->
3 <ng-template #dropdownToggle let-col="col"> 
4   <span i18n>Filter</span>
5   <ng-container *ngIf="!col.isFiltered">
6     <span class="material-icons mat-icon-in-button">filter_list</span>
7   </ng-container>
8   <ng-container *ngIf="col.isFiltered">
9     <span class="material-icons mat-icon-in-button">create</span>
10   </ng-container>
11 </ng-template>
12
13 <!-- apply/clear actions are the same for all filter types -->
14 <ng-template #actionsTemplate let-col="col">
15   <div class="pt-2">
16     <button class="btn btn-sm btn-outline-dark" 
17       (click)="closeDropdown(); applyFilter(col)" i18n>Apply filter</button>
18     <span class="pl-2"></span>
19     <button class="btn btn-sm btn-outline-dark" 
20       (click)="closeDropdown(); clearFilter(col)" i18n>Clear filter</button>
21   </div>
22 </ng-template>
23
24 <!-- various number filters all use the same operators -->
25 <ng-template #numericOperators let-col="col">
26   <select id="eg-filter-op-select-{{col.name}}" class="form-control" 
27     [(ngModel)]="col.filterOperator" (change)="operatorChanged(col)">
28     <option value="=" i18n>Is exactly</option>
29     <option value="!=" i18n>Is not</option>
30     <option value="not null" i18n>Exists</option>
31     <option value="null" i18n>Does not exist</option>
32     <option value="<" i18n>Is less than</option>
33     <option value=">" i18n>Is greater than</option>
34     <option value="<=" i18n>Is less than or equal to</option>
35     <option value=">=" i18n>Is greater than or equal to</option>
36   </select>
37 </ng-template>
38
39 <div *ngIf="col.isFilterable" class="eg-grid-filter-control">
40   <div [ngSwitch]="col.datatype">
41     <div *ngSwitchCase="'link'">
42       <div class="input-group">
43         <div ngbDropdown container="body" class="d-inline-block p-1" autoClose="outside" placement="bottom-left" 
44           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
45           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
46             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
47           </a>
48           <div ngbDropdownMenu class="eg-grid-filter-menu">
49             <div class="dropdown-item">
50               <div class="pt-2">
51                 <eg-combobox [asyncSupportsEmptyTermClick]="col.asyncSupportsEmptyTermClick" 
52                   [idlClass]="col.idlFieldDef.class" (onChange)="applyLinkFilter($event, col)" 
53                   [disabled]="col.filterInputDisabled || context.dataSource.requestingData"
54                   i18n-placeholder placeholder="Enter value to filter by"></eg-combobox>
55               </div>
56               <ng-container *ngTemplateOutlet="actionsTemplate; context:{col: col}"></ng-container>
57             </div>
58           </div>
59         </div>
60       </div>
61     </div>
62     <div *ngSwitchCase="'bool'">
63       <div class="input-group">
64         <div ngbDropdown container="body" class="d-inline-block p-1" autoClose="outside" placement="bottom-left" 
65           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
66           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
67             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
68           </a>
69           <div ngbDropdownMenu class="eg-grid-filter-menu">
70             <div class="dropdown-item">
71               <div class="pt-2">
72                 <select class="custom-select" [(ngModel)]="col.filterValue" (change)="applyBooleanFilter(col)"
73                     [disabled]="col.filterInputDisabled || context.dataSource.requestingData">
74                   <option value="" i18n>Any</option>
75                   <option value="t" i18n>True</option>
76                   <option value="f" i18n>False</option>
77                 </select>
78               </div>
79               <ng-container *ngTemplateOutlet="actionsTemplate; context:{'col': col}"></ng-container>
80             </div>
81           </div>
82         </div>
83       </div>
84     </div>
85     <div *ngSwitchCase="'text'">
86       <div class="input-group">
87         <div ngbDropdown container="body" class="d-inline-block p-1" autoClose="outside" placement="bottom-left" 
88           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
89           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
90             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
91           </a>
92           <div ngbDropdownMenu class="eg-grid-filter-menu">
93             <div class="dropdown-item">
94               <div class="pt-2">
95                 <label for="eg-filter-op-select-{{col.name}}" i18n>Operator</label>
96                 <select id="eg-filter-op-select-{{col.name}}" class="form-control" 
97                   [(ngModel)]="col.filterOperator" (change)="operatorChanged(col)">
98                   <option value="=" i18n>Is exactly</option>
99                   <option value="!=" i18n>Is not</option>
100                   <option value="like" i18n>Contains</option>
101                   <option value="not like" i18n>Does not contain</option>
102                   <option value="startswith" i18n>Starts with</option>
103                   <option value="endswith" i18n>Ends with</option>
104                   <option value="not null" i18n>Exists</option>
105                   <option value="null" i18n>Does not exist</option>
106                   <option value="<" i18n>Is less than</option>
107                   <option value=">" i18n>Is greater than</option>
108                   <option value="<=" i18n>Is less than or equal to</option>
109                   <option value=">=" i18n>Is greater than or equal to</option>
110                 </select>
111               </div>
112               <div class="pt-2">
113                 <input type="text" class="form-control" 
114                   [(ngModel)]="col.filterValue" (keyup.enter)="applyFilter(col); closeDropdown()" 
115                   [disabled]="col.filterInputDisabled || context.dataSource.requestingData" 
116                   i18n-placeholder placeholder="Enter value to filter by">
117               </div>
118               <ng-container *ngTemplateOutlet="actionsTemplate; context:{'col': col}"></ng-container>
119             </div>
120           </div>
121         </div>
122       </div>
123     </div>
124     <div *ngSwitchCase="'int'">
125       <div class="input-group">
126         <div ngbDropdown container="body" class="d-inline-block p-1" autoClose="outside" placement="bottom-left" 
127           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
128           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
129             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
130           </a>
131           <div ngbDropdownMenu class="eg-grid-filter-menu">
132             <div class="dropdown-item">
133               <div class="pt-2">
134                 <label for="eg-filter-op-select-{{col.name}}" i18n>Operator</label>
135                 <ng-container *ngTemplateOutlet="numericOperators; context:{'col': col}"></ng-container>
136               </div>
137               <div class="pt-2">
138                 <input type="number" min="0" step="1" class="form-control" 
139                   [(ngModel)]="col.filterValue" (keyup.enter)="applyFilter(col); closeDropdown()" 
140                   [disabled]="col.filterInputDisabled || context.dataSource.requestingData"/>
141               </div>
142               <ng-container *ngTemplateOutlet="actionsTemplate; context:{'col': col}"></ng-container>
143             </div>
144           </div>
145         </div>
146       </div>
147     </div>
148     <div *ngSwitchCase="'id'">
149       <div class="input-group">
150         <div ngbDropdown container="body" class="d-inline-block p-1" autoClose="outside" placement="bottom-left" 
151           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
152           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
153             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
154           </a>
155           <div ngbDropdownMenu class="eg-grid-filter-menu">
156             <div class="dropdown-item">
157               <div class="pt-2">
158                 <label for="eg-filter-op-select-{{col.name}}" i18n>Operator</label>
159                 <ng-container *ngTemplateOutlet="numericOperators; context:{'col': col}"></ng-container>
160               </div>
161               <div class="pt-2">
162                 <input type="number" min="0" step="1" class="form-control" 
163                   [(ngModel)]="col.filterValue" (keyup.enter)="applyFilter(col); closeDropdown()" 
164                   [disabled]="col.filterInputDisabled || context.dataSource.requestingData">
165               </div>
166               <ng-container *ngTemplateOutlet="actionsTemplate; context:{'col': col}"></ng-container>
167             </div>
168           </div>
169         </div>
170       </div>
171     </div>
172     <div *ngSwitchCase="'float'">
173       <div class="input-group">
174         <div ngbDropdown container="body" class="d-inline-block p-1" autoClose="outside" placement="bottom-left" 
175           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
176           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
177             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
178           </a>
179           <div ngbDropdownMenu class="eg-grid-filter-menu">
180             <div class="dropdown-item">
181               <div class="pt-2">
182                 <label for="eg-filter-op-select-{{col.name}}" i18n>Operator</label>
183                 <ng-container *ngTemplateOutlet="numericOperators; context:{'col': col}"></ng-container>
184               </div>
185               <div class="pt-2">
186                 <input type="number" class="form-control" [(ngModel)]="col.filterValue" 
187                   (keyup.enter)="applyFilter(col); closeDropdown()" 
188                   [disabled]="col.filterInputDisabled || context.dataSource.requestingData">
189               </div>
190               <ng-container *ngTemplateOutlet="actionsTemplate; context:{'col': col}"></ng-container>
191             </div>
192           </div>
193         </div>
194       </div>
195     </div>
196     <div *ngSwitchCase="'money'">
197       <div class="input-group">
198         <div ngbDropdown container="body" class="d-inline-block p-1" autoClose="outside" placement="bottom-left" 
199           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
200           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
201             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
202           </a>
203           <div ngbDropdownMenu class="eg-grid-filter-menu">
204             <div class="dropdown-item">
205               <div class="pt-2">
206                 <label for="eg-filter-op-select-{{col.name}}" i18n>Operator</label>
207                 <ng-container *ngTemplateOutlet="numericOperators; context:{'col': col}"></ng-container>
208               </div>
209               <div class="pt-2">
210                 <input type="number" step="0.01" class="form-control" 
211                   [(ngModel)]="col.filterValue" (keyup.enter)="applyFilter(col); closeDropdown()" 
212                   [disabled]="col.filterInputDisabled || context.dataSource.requestingData"/>
213               </div>
214               <ng-container *ngTemplateOutlet="actionsTemplate; context:{'col': col}"></ng-container>
215             </div>
216          </div>
217         </div>
218       </div>
219     </div>
220     <div *ngSwitchCase="'timestamp'">
221       <div class="input-group">
222         <!-- [autoClose]="false" because editing the date widgets, which open
223              their open popups, registers to the dropdown as clicking 
224              outside the dropdown -->
225         <div ngbDropdown container="body" class="d-inline-block p-1" [autoClose]="false" placement="bottom-left" 
226           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
227           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
228             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
229           </a>
230           <div ngbDropdownMenu class="eg-grid-filter-menu">
231             <div class="dropdown-item">
232               <div class="pt-2">
233                 <label for="eg-filter-op-select-{{col.name}}" i18n>Operator</label>
234                 <select id="eg-filter-op-select-{{col.name}}" class="form-control" 
235                   [(ngModel)]="col.filterOperator" (change)="operatorChanged(col)">
236                   <option value="=" i18n>Is exactly</option>
237                   <option value="!=" i18n>Is not</option>
238                   <option value="not null" i18n>Exists</option>
239                   <option value="null" i18n>Does not exist</option>
240                   <option value="<" i18n>Is less than</option>
241                   <option value=">" i18n>Is greater than</option>
242                   <option value="<=" i18n>Is less than or equal to</option>
243                   <option value=">=" i18n>Is greater than or equal to</option>
244                   <option value="between" i18n>Between</option>
245                 </select>
246               </div>
247               <div class="pt-2">
248                 <eg-date-select [initialYmd]="col.filterValue" 
249                   (onChangeAsYmd)="applyDateFilter($event, col, dateendsel.currentAsYmd())" (onCleared)="clearDateFilter(col)"
250                   [disabled]="col.filterInputDisabled || context.dataSource.requestingData" #datesel></eg-date-select>
251                 <div [hidden]="col.filterOperator !== 'between'" class="form-inline form-group">
252                   <label for="eg-filter-end-date-select-{{col.name}}" style="width: 3em;" i18n>and</label>
253                   <eg-date-select [hidden]="col.filterOperator !== 'between'" 
254                     (onChangeAsYmd)="applyDateFilter(datesel.currentAsYmd(), col, $event)"
255                     [disabled]="col.filterInputDisabled || context.dataSource.requestingData"
256                     [required]="col.filterOperator == 'between'" #dateendsel></eg-date-select>
257                 </div>
258               </div>
259               <ng-container *ngTemplateOutlet="actionsTemplate; context:{'col': col}"></ng-container>
260             </div>
261           </div>
262         </div>
263       </div>
264     </div>
265     <div *ngSwitchCase="'org_unit'">
266       <div class="input-group">
267         <div ngbDropdown container="body" class="d-inline-block p-1" autoClose="outside" placement="bottom-left" 
268           [ngClass]="{'border rounded border-secondary eg-grid-col-is-filtered' : col.isFiltered}">
269           <a ngbDropdownToggle class="no-dropdown-caret text-dark" href="javascript:;">
270             <ng-container *ngTemplateOutlet="dropdownToggle; context:{col:col}"></ng-container>
271           </a>
272           <div ngbDropdownMenu class="eg-grid-filter-menu">
273             <div class="dropdown-item">
274               <div class="pt-2">
275                 <label for="eg-filter-op-select-{{col.name}}" i18n>Operator</label>
276                 <select id="eg-filter-op-select-{{col.name}}" class="form-control" [(ngModel)]="col.filterOperator" (change)="operatorChanged(col)">
277                   <option value="=" i18n>Is (or includes)</option>
278                   <option value="!=" i18n>Is not (or excludes)</option>
279                 </select>
280               </div>
281               <div class="dropdown-item">
282                 <div class="form-check">
283                   <input type="checkbox"
284                     [(ngModel)]="col.filterIncludeOrgAncestors"
285                     class="form-check-input" id="include-ancestors">
286                   <label class="form-check-label" for="include-ancestors" i18n>+ Ancestors</label>
287                 </div>
288                 <div class="form-check">
289                   <input type="checkbox"
290                     [(ngModel)]="col.filterIncludeOrgDescendants"
291                     class="form-check-input" id="include-descendants">
292                   <label class="form-check-label" for="include-descendants" i18n>+ Descendants</label>
293                 </div>
294               </div>
295               <div class="pt-2">
296                 <eg-org-select [applyOrgId]="col.filterValue" (onChange)="applyOrgFilter($event, col)"
297                   [disabled]="col.filterInputDisabled || context.dataSource.requestingData"
298                   i18n-placeholder placeholder="Enter library to filter by" #ousel></eg-org-select>
299               </div>
300               <ng-container *ngTemplateOutlet="actionsTemplate; context:{'col': col}"></ng-container>
301             </div>
302           </div>
303         </div>
304       </div>
305     </div>
306     <div *ngSwitchDefault>I don't know how to filter {{col.name}} - {{col.datatype}}</div>
307   </div>
308   <!--
309   <span *ngIf="col.datatype !== 'org_unit'" class="eg-grid-filter-operator"><ng-container i18n>Operator:</ng-container>
310     <span [ngSwitch]="col.filterOperator">
311       <span *ngSwitchCase="'='" i18n>Is exactly</span>
312       <span *ngSwitchCase="'!='" i18n>Is not</span>
313       <span *ngSwitchCase="'>'" i18n>Is greater than</span>
314       <span *ngSwitchCase="'>='" i18n>Is greater than or equal to</span>
315       <span *ngSwitchCase="'<'" i18n>Is less than</span>
316       <span *ngSwitchCase="'<='" i18n>Is less than or equal to</span>
317       <span *ngSwitchCase="'like'" i18n>Contains</span>
318       <span *ngSwitchCase="'not like'" i18n>Does not contain</span>
319       <span *ngSwitchCase="'startswith'" i18n>Starts with</span>
320       <span *ngSwitchCase="'endswith'" i18n>Ends with</span>
321       <span *ngSwitchCase="'null'" i18n>Does not exist</span>
322       <span *ngSwitchCase="'not null'" i18n>Exists</span>
323       <span *ngSwitchCase="'between'" i18n>Between</span>
324     </span>
325   </span>
326   <span *ngIf="col.datatype == 'org_unit'" class="eg-grid-filter-operator"><ng-container i18n>Operator:</ng-container>
327     <span [ngSwitch]="col.filterOperator">
328       <span *ngSwitchCase="'='" i18n>Is (or includes)</span>
329       <span *ngSwitchCase="'!='" i18n>Is not (or excludes)</span>
330     </span>
331   </span>
332   -->
333 </div>