Skip to content

Commit eb8ca16

Browse files
committed
Merge branch 'dmdimitrov/query-builder-improvements' into mcherkasov/qb-rehydration
2 parents 2bf21ad + 33199c2 commit eb8ca16

File tree

4 files changed

+426
-390
lines changed

4 files changed

+426
-390
lines changed

projects/igniteui-angular/src/lib/query-builder/query-builder-functions.spec.ts

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -530,10 +530,10 @@ export class QueryBuilderFunctions {
530530
public static verifyEditModeQueryExpressionInputStates(fix,
531531
entitySelectEnabled: boolean,
532532
fieldComboEnabled: boolean,
533-
columnSelectEnabled: boolean,
534-
operatorSelectEnabled: boolean,
535-
valueInputEnabled: boolean,
536-
commitButtonEnabled: boolean,
533+
columnSelectEnabled?: boolean,
534+
operatorSelectEnabled?: boolean,
535+
valueInputEnabled?: boolean,
536+
commitButtonEnabled?: boolean,
537537
level = 0) {
538538
// Verify the entity select state.
539539
const entityInputGroup = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, level).querySelector('igx-input-group');
@@ -544,7 +544,9 @@ export class QueryBuilderFunctions {
544544
expect(!fieldInputGroup.classList.contains('igx-input-group--disabled')).toBe(fieldComboEnabled,
545545
'incorrect fields combo state');
546546

547-
QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, columnSelectEnabled, operatorSelectEnabled, valueInputEnabled, commitButtonEnabled, level);
547+
if(columnSelectEnabled || operatorSelectEnabled || valueInputEnabled || commitButtonEnabled){
548+
QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, columnSelectEnabled, operatorSelectEnabled, valueInputEnabled, commitButtonEnabled, level);
549+
}
548550
};
549551

550552
public static verifyEditModeExpressionInputStates(fix,
@@ -581,15 +583,18 @@ export class QueryBuilderFunctions {
581583
public static verifyQueryEditModeExpressionInputValues(fix,
582584
entityText: string,
583585
fieldsText: string,
584-
columnText: string,
585-
operatorText: string,
586-
valueText: string,
586+
columnText?: string,
587+
operatorText?: string,
588+
valueText?: string,
587589
level = 0) {
588590
const entityInput = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, level).querySelector('input');
589591
const fieldInput = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fix, level).querySelector('input');
590-
QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, columnText, operatorText, valueText, level);
591592
expect(entityInput.value).toBe(entityText);
592593
expect(fieldInput.value).toBe(fieldsText);
594+
595+
if(columnText || operatorText || valueText){
596+
QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, columnText, operatorText, valueText, level);
597+
}
593598
};
594599

595600
public static verifyEditModeExpressionInputValues(fix,
@@ -664,9 +669,9 @@ export class QueryBuilderFunctions {
664669
let i = 0;
665670
tabElements.forEach((element: HTMLElement) => {
666671
switch (i) {
667-
case 0: expect(element).toHaveClass('igx-filter-tree__line--and'); break;
672+
case 0: expect(element).toHaveClass('igx-input-group__input'); break;
668673
case 1: expect(element).toHaveClass('igx-input-group__input'); break;
669-
case 2: expect(element).toHaveClass('igx-input-group__input'); break;
674+
case 2: expect(element).toHaveClass('igx-filter-tree__line--and'); break;
670675
case 3: expect(element).toHaveClass('igx-chip'); break;
671676
case 4: expect(element).toHaveClass('igx-chip__remove'); break;
672677
case 5: expect(element).toHaveClass('igx-filter-tree__details-button'); break;
@@ -723,9 +728,9 @@ export class QueryBuilderFunctions {
723728
let i = 0;
724729
tabElements.forEach((element: HTMLElement) => {
725730
switch (i) {
726-
case 0: expect(element).toHaveClass('igx-filter-tree__line--and'); break;
731+
case 0: expect(element).toHaveClass('igx-input-group__input'); break;
727732
case 1: expect(element).toHaveClass('igx-input-group__input'); break;
728-
case 2: expect(element).toHaveClass('igx-input-group__input'); break;
733+
case 2: expect(element).toHaveClass('igx-filter-tree__line--and'); break;
729734
case 3: expect(element).toHaveClass('igx-chip'); break;
730735
case 4: expect(element).toHaveClass('igx-chip__remove'); break;
731736
case 5: expect(element).toHaveClass('igx-chip'); break;
@@ -825,39 +830,18 @@ export class QueryBuilderFunctions {
825830
fix.detectChanges();
826831
}
827832

828-
public static addChildGroup(fix: ComponentFixture<any>, groupType: number, level: number) {
829-
// Click the initial 'Add Or Group' button.
830-
QueryBuilderFunctions.clickQueryBuilderInitialAddGroupButton(fix, groupType, level);
831-
tick(100);
832-
fix.detectChanges();
833-
833+
public static addAndValidateChildGroup(fix: ComponentFixture<any>, groupType: number, level: number) {
834+
// Enter values in the nested query
834835
QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0, level); // Select 'Products' entity
835836
tick(100);
836837
fix.detectChanges();
837838

838-
QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1, level); // Select 'ProductName' column.
839-
QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0, level); // Select 'Contains' operator.
840-
const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false, level).querySelector('input');
841-
UIInteractions.clickAndSendInputElementValue(input, 'a');
842-
tick(100);
843-
fix.detectChanges();
844-
845-
//Commit the populated expression.
846-
QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix, level);
847-
fix.detectChanges();
848-
}
849-
850-
public static addAndValidateChildGroup(fix: ComponentFixture<any>, groupType: number, level: number) {
851839
// Click the initial 'Add Or Group' button.
852840
QueryBuilderFunctions.clickQueryBuilderInitialAddGroupButton(fix, groupType, level);
853841
tick(100);
854842
fix.detectChanges();
855843

856-
QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, false, false, false, false, false, level);
857-
// Enter values in the nested query
858-
QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0, level); // Select 'Products' entity
859-
tick(100);
860-
fix.detectChanges();
844+
QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, false, false, false, false, level);
861845

862846
QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, false, false, false, level);
863847

@@ -902,4 +886,15 @@ export class QueryBuilderFunctions {
902886
tick();
903887
fix.detectChanges();
904888
}
889+
890+
public static selectEntityAndClickInitialAddGroup(fix: ComponentFixture<any>, entityIndex: number, groupIndex: number) {
891+
QueryBuilderFunctions.selectEntityInEditModeExpression(fix, entityIndex);
892+
tick(100);
893+
fix.detectChanges();
894+
895+
// Click the initial 'Add Or Group' button.
896+
QueryBuilderFunctions.clickQueryBuilderInitialAddGroupButton(fix, groupIndex);
897+
tick(100);
898+
fix.detectChanges();
899+
}
905900
}

projects/igniteui-angular/src/lib/query-builder/query-builder-tree.component.html

Lines changed: 57 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,66 @@
66
<igx-icon family="default" name="close"></igx-icon>
77
</ng-template>
88

9+
<ng-template #selectFromTemplate>
10+
<div class="igx-filter-tree__inputs" [style.display]="(isInEditMode() && !this.isAdvancedFiltering()) ? 'flex' : 'none'">
11+
<igx-select #entitySelect
12+
type="box"
13+
(selectionChanging)="onEntitySelectChanging($event)"
14+
[overlaySettings]="entitySelectOverlaySettings"
15+
[ngModel]="selectedEntity"
16+
[style.display]="isInEditMode() ? 'block' : 'none'"
17+
>
18+
<label igxLabel>{{ this.resourceStrings.igx_query_builder_select_entity }}</label>
19+
<igx-select-item *ngFor="let entity of entities" [value]="entity">
20+
{{entity.name}}
21+
</igx-select-item>
22+
</igx-select>
23+
24+
<igx-combo
25+
#selectedReturnFieldsCombo
26+
[itemsMaxHeight]="250"
27+
[data]="fields"
28+
[displayKey]="'field'"
29+
[valueKey]="'field'"
30+
[disabled]="!selectedEntity"
31+
[(ngModel)]="selectedReturnFields"
32+
[overlaySettings]="returnFieldSelectOverlaySettings"
33+
searchPlaceholder="{{ this.resourceStrings.igx_query_builder_search }}"
34+
[style.display]="isInEditMode() ? 'block' : 'none'"
35+
(selectionChanging)="onReturnFieldSelectChanging($event)"
36+
>
37+
<ng-template igxComboHeader>
38+
<div
39+
class="igx-drop-down__item igx-drop-down__item--query-builder"
40+
(click)="onSelectAllClicked($event)"
41+
[ngClass]="{'igx-drop-down__item--selected': this.selectedEntity && this.selectedReturnFields && this.selectedEntity.fields.length === this.selectedReturnFields.length}"
42+
>
43+
<igx-checkbox
44+
[checked]="this.selectedEntity && this.selectedReturnFields && this.selectedEntity.fields.length === this.selectedReturnFields.length"
45+
[indeterminate]="this.selectedEntity && this.selectedReturnFields && this.selectedReturnFields.length > 0 && this.selectedReturnFields.length < this.selectedEntity.fields?.length"
46+
[readonly]="true"
47+
[disableRipple]="true"
48+
[tabindex]="-1"
49+
class="igx-combo__checkbox">
50+
</igx-checkbox>
51+
<div class="igx-drop-down__inner">
52+
{{ this.resourceStrings.igx_query_builder_select_all }}
53+
</div>
54+
</div>
55+
</ng-template>
56+
<label igxLabel>{{ this.resourceStrings.igx_query_builder_select_return_fields }}</label>
57+
</igx-combo>
58+
</div>
59+
</ng-template>
60+
961
<div
1062
#expressionsContainer
1163
class="igx-query-builder__main"
64+
style="display: grid;"
1265
(scroll)="onExpressionsScrolled()"
1366
>
14-
<ng-container *ngIf="!rootGroup">
67+
<ng-container *ngTemplateOutlet="selectFromTemplate"></ng-container>
68+
<ng-container *ngIf="!rootGroup && (selectedEntity || (entities?.length === 1 && !entities[0]?.name))">
1569
<div class="igx-query-builder__root">
1670
<div class="igx-query-builder__root-actions">
1771
<button type="button"
@@ -192,7 +246,7 @@ <h6 class="igx-filter-empty__title">
192246
<igx-icon id="add-expression">add</igx-icon>
193247
</button>
194248
</div>
195-
<div *ngIf="!expressionItem.inEditMode && expressionItem.expression.searchTree"
249+
<div *ngIf="!expressionItem.inEditMode && expressionItem.expression.searchTree && expressionItem.expression.searchTree.filteringOperands.length > 0"
196250
igxButton
197251
class="igx-filter-tree__details-button"
198252
(click)="expanderClick($event, expressionItem)"
@@ -452,58 +506,7 @@ <h6 class="igx-filter-empty__title">
452506
(click)="onGroupClick(expressionItem)"
453507
></div>
454508

455-
<div class="igx-filter-tree__expression">
456-
<div class="igx-filter-tree__inputs" [style.display]="(isInEditMode() && this.entities.length > 0 && this.entities[0].name) ? 'flex' : 'none'">
457-
<ng-container *ngIf="!expressionItem.parent">
458-
<igx-select #entitySelect
459-
type="box"
460-
(selectionChanging)="onEntitySelectChanging($event)"
461-
[overlaySettings]="entitySelectOverlaySettings"
462-
[ngModel]="selectedEntity"
463-
[style.display]="isInEditMode() ? 'block' : 'none'"
464-
>
465-
<label igxLabel>{{ this.resourceStrings.igx_query_builder_select_entity }}</label>
466-
<igx-select-item *ngFor="let entity of entities" [value]="entity">
467-
{{entity.name}}
468-
</igx-select-item>
469-
</igx-select>
470-
471-
<igx-combo
472-
#selectedReturnFieldsCombo
473-
[itemsMaxHeight]="250"
474-
[data]="fields"
475-
[displayKey]="'field'"
476-
[valueKey]="'field'"
477-
[disabled]="!selectedEntity"
478-
[(ngModel)]="selectedReturnFields"
479-
[overlaySettings]="returnFieldSelectOverlaySettings"
480-
searchPlaceholder="{{ this.resourceStrings.igx_query_builder_search }}"
481-
[style.display]="isInEditMode() ? 'block' : 'none'"
482-
>
483-
<ng-template igxComboHeader>
484-
<div
485-
class="igx-drop-down__item igx-drop-down__item--query-builder"
486-
(click)="onSelectAllClicked($event)"
487-
[ngClass]="{'igx-drop-down__item--selected': this.selectedEntity && this.selectedReturnFields && this.selectedEntity.fields.length === this.selectedReturnFields.length}"
488-
>
489-
<igx-checkbox
490-
[checked]="this.selectedEntity && this.selectedReturnFields && this.selectedEntity.fields.length === this.selectedReturnFields.length"
491-
[indeterminate]="this.selectedEntity && this.selectedReturnFields && this.selectedReturnFields.length > 0 && this.selectedReturnFields.length < this.selectedEntity.fields?.length"
492-
[readonly]="true"
493-
[disableRipple]="true"
494-
[tabindex]="-1"
495-
class="igx-combo__checkbox">
496-
</igx-checkbox>
497-
<div class="igx-drop-down__inner">
498-
{{ this.resourceStrings.igx_query_builder_select_all }}
499-
</div>
500-
</div>
501-
</ng-template>
502-
<label igxLabel>{{ this.resourceStrings.igx_query_builder_select_return_fields }}</label>
503-
</igx-combo>
504-
</ng-container>
505-
</div>
506-
509+
<div class="igx-filter-tree__expression">
507510
<ng-container *ngFor="let expr of expressionItem?.children">
508511
<ng-container
509512
*ngTemplateOutlet="

0 commit comments

Comments
 (0)