Skip to content

Commit 1e4ad30

Browse files
committed
Merge branch 'ipetrov/query-builder-drag-and-drop-refactor-master' into ipetrov/query-builder-drag-and-drop-refactor-remake2-master
2 parents 93ff065 + e94b76a commit 1e4ad30

File tree

8 files changed

+581
-463
lines changed

8 files changed

+581
-463
lines changed

projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-component.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@
107107
@extend %filter-tree__expression-item !optional;
108108
}
109109

110-
@include e(expression-item-ghost) {
110+
@include e(expression-item-drop-ghost) {
111111
@extend %filter-tree__expression-item-ghost !optional;
112112
}
113113

114-
@include e(expression-item-drop-ghost) {
115-
@extend %filter-tree__expression-drop-item-ghost !optional;
114+
@include e(expression-item-keyboard-ghost) {
115+
@extend %filter-tree__expression-item-keyboard-ghost !optional;
116116
}
117117

118118
@include e(expression-column) {

projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-theme.scss

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -480,18 +480,25 @@
480480

481481

482482
%filter-tree__expression-item-ghost {
483-
&.igx-chip__item {
483+
.igx-chip__item {
484484
@include type-style('body-2');
485485

486486
--ig-body-2-text-transform: unset;
487487

488488
padding-inline: rem(32px);
489+
490+
color: color($color: 'gray', $variant: if($theme-variant == 'light', 600, 900));
491+
border: rem(1px) dashed color($color: 'gray', $variant: if($theme-variant == 'light', 600, 300));
492+
background: transparent;
489493
}
490-
491-
color: color($color: 'gray', $variant: if($theme-variant == 'light', 600, 900));
492-
border: rem(1px) dashed color($color: 'gray', $variant: if($theme-variant == 'light', 600, 300));
493-
background: transparent;
494494
}
495+
496+
%filter-tree__expression-item-keyboard-ghost {
497+
.igx-chip__item {
498+
box-shadow: var(--ghost-shadow);
499+
background: var(--ghost-background);
500+
}
501+
}
495502

496503
%filter-tree__expression-column {
497504
padding: 0 rem(8px);

projects/igniteui-angular/src/lib/query-builder/query-builder-drag.service.ts

Lines changed: 275 additions & 337 deletions
Large diffs are not rendered by default.

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

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ export class QueryBuilderFunctions {
865865
}
866866

867867
public static getChipContent(chip: Element): string {
868-
if (chip.checkVisibility()) {
868+
if (chip && chip.checkVisibility()) {
869869
let text: string = '';
870870

871871
Array.from(chip.querySelectorAll('span')).forEach(element => {
@@ -883,7 +883,8 @@ export class QueryBuilderFunctions {
883883

884884
public static getDropGhost(fixture: ComponentFixture<any>): Element {
885885
var expressionsContainer = QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fixture);
886-
return expressionsContainer.querySelector(`div.${QueryBuilderSelectors.FILTER_TREE_EXPRESSION_ITEM_DROP_GHOST}`);
886+
return expressionsContainer.querySelector(`div.${QueryBuilderSelectors.FILTER_TREE_EXPRESSION_ITEM_DROP_GHOST}`) ??
887+
expressionsContainer.querySelector(`div.${QueryBuilderSelectors.FILTER_TREE_EXPRESSION_ITEM_KEYBOARD_GHOST}`);
887888
}
888889

889890
public static getDropGhostBounds(fixture: ComponentFixture<any>): DOMRect {
@@ -910,4 +911,27 @@ export class QueryBuilderFunctions {
910911
dragDirective.onPointerUp({ pointerId: 1, pageX: X, pageY: Y });
911912
}
912913
}
914+
915+
public static getDropGhostAndItsSiblings(fixture: ComponentFixture<any>): [Element, string, string, string[]] {
916+
const dropGhost = this.getDropGhost(fixture);
917+
const newChipContents = QueryBuilderFunctions.GetChipsContentAsArray(fixture);
918+
let prevElement: string, nextElement: string;
919+
920+
if (dropGhost) {
921+
if (dropGhost.previousElementSibling?.className &&
922+
dropGhost.previousElementSibling?.className?.indexOf(QueryBuilderSelectors.FILTER_TREE_SUBQUERY) !== -1) {
923+
prevElement = QueryBuilderFunctions.getChipContent(dropGhost.previousElementSibling.previousElementSibling);
924+
} else if (dropGhost.previousElementSibling?.previousElementSibling) {
925+
prevElement = QueryBuilderFunctions.getChipContent(dropGhost.previousElementSibling);
926+
}
927+
928+
nextElement = QueryBuilderFunctions.getChipContent(dropGhost.nextElementSibling?.nextElementSibling);
929+
nextElement ??= QueryBuilderFunctions.getChipContent(dropGhost.nextElementSibling?.nextElementSibling?.nextElementSibling?.nextElementSibling);
930+
}
931+
932+
prevElement ??= null;
933+
nextElement ??= null;
934+
935+
return [dropGhost, prevElement, nextElement, newChipContents];
936+
}
913937
}

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,24 @@
125125

126126
<ng-template #operandTemplate let-expressionItem>
127127
@if (!expressionItem.inEditMode) {
128+
@if(dragService.dropGhostExpression && expressionItem === dragService.dropGhostExpression && dragService.isKeyboardDrag === false){
129+
<div class="igx-filter-tree__expression-item igx-filter-tree__expression-item-drop-ghost">
130+
<igx-chip [data]="expressionItem">
131+
{{this.resourceStrings.igx_query_builder_drop_ghost_text}}
132+
</igx-chip>
133+
</div>
134+
} @else {
128135
<div
129136
#dragRef
130137
igxDrop
131138
(enter)="dragService.onChipEnter(dragRef, expressionItem)"
132139
(over)="dragService.onDivOver(dragRef, expressionItem)"
133140
(leave)="dragService.onChipLeave()"
134141
(dropped)="dragService.onDivDropped(expressionItem)"
135-
class="igx-filter-tree__expression-item"
142+
[ngClass]="{
143+
'igx-filter-tree__expression-item': true,
144+
'igx-filter-tree__expression-item-keyboard-ghost': expressionItem === dragService.dropGhostExpression
145+
}"
136146
(mouseenter)="expressionItem.hovered = true"
137147
(mouseleave)="expressionItem.hovered = false"
138148
(focusin)="onExpressionFocus(expressionItem)"
@@ -263,6 +273,7 @@
263273
}
264274
</div>
265275
}
276+
}
266277
<div #editingInputsContainer class="igx-filter-tree__subquery" >
267278
@if (expressionItem.inEditMode) {
268279
<div

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

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -68,40 +68,53 @@ const DEFAULT_CHIP_FOCUS_DELAY = 50;
6868
templateUrl: './query-builder-tree.component.html',
6969
host: { 'class': 'igx-query-builder-tree' },
7070
imports: [
71-
DatePipe,
72-
FormsModule,
73-
IgxButtonDirective,
74-
IgxCheckboxComponent,
75-
IgxChipComponent,
76-
IgxComboComponent,
77-
IgxComboHeaderDirective,
78-
IgxDatePickerComponent,
79-
IgxDateTimeEditorDirective,
80-
IgxDialogComponent,
81-
IgxDragIgnoreDirective,
82-
IgxDropDirective,
83-
IgxDropDownComponent,
84-
IgxDropDownItemComponent,
85-
IgxDropDownItemNavigationDirective,
86-
IgxFieldFormatterPipe,
87-
IgxIconButtonDirective,
88-
IgxIconComponent,
89-
IgxInputDirective,
90-
IgxInputGroupComponent,
91-
IgxOverlayOutletDirective,
92-
IgxPickerClearComponent,
93-
IgxPickerToggleComponent,
94-
IgxPrefixDirective,
95-
IgxSelectComponent,
96-
IgxSelectItemComponent,
97-
IgxTimePickerComponent,
98-
IgxTooltipDirective,
99-
IgxTooltipTargetDirective,
100-
NgClass,
101-
NgTemplateOutlet
102-
]
71+
DatePipe,
72+
FormsModule,
73+
IgxButtonDirective,
74+
IgxCheckboxComponent,
75+
IgxChipComponent,
76+
IgxComboComponent,
77+
IgxComboHeaderDirective,
78+
IgxDatePickerComponent,
79+
IgxDateTimeEditorDirective,
80+
IgxDialogComponent,
81+
IgxDragIgnoreDirective,
82+
IgxDropDirective,
83+
IgxDropDownComponent,
84+
IgxDropDownItemComponent,
85+
IgxDropDownItemNavigationDirective,
86+
IgxFieldFormatterPipe,
87+
IgxIconButtonDirective,
88+
IgxIconComponent,
89+
IgxInputDirective,
90+
IgxInputGroupComponent,
91+
IgxOverlayOutletDirective,
92+
IgxPickerClearComponent,
93+
IgxPickerToggleComponent,
94+
IgxPrefixDirective,
95+
IgxSelectComponent,
96+
IgxSelectItemComponent,
97+
IgxTimePickerComponent,
98+
IgxTooltipDirective,
99+
IgxTooltipTargetDirective,
100+
NgClass,
101+
NgTemplateOutlet
102+
],
103+
providers: [
104+
IgxQueryBuilderDragService
105+
],
103106
})
104107
export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
108+
/**
109+
* @hidden @internal
110+
*/
111+
public _expressionTree: IExpressionTree;
112+
113+
/**
114+
* @hidden @internal
115+
*/
116+
public _expressionTreeCopy: IExpressionTree;
117+
105118
/**
106119
* @hidden @internal
107120
*/
@@ -285,8 +298,11 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
285298
@ViewChild('groupContextMenuDropDown', { read: IgxDropDownComponent })
286299
private groupContextMenuDropDown: IgxDropDownComponent;
287300

301+
/**
302+
* @hidden @internal
303+
*/
288304
@ViewChildren(IgxChipComponent, { read: IgxChipComponent })
289-
private expressionsChips: QueryList<IgxChipComponent>;
305+
public expressionsChips: QueryList<IgxChipComponent>;
290306

291307
@ViewChild('editingInputsContainer', { read: ElementRef })
292308
protected set editingInputsContainer(value: ElementRef) {
@@ -456,7 +472,6 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
456472
private _prevFocusedContainer: ElementRef;
457473
private _expandedExpressions: IFilteringExpression[] = [];
458474
private _fields: FieldType[];
459-
private _expressionTree: IExpressionTree;
460475
private _locale;
461476
private _entityNewValue: EntityType;
462477
private _resourceStrings = getCurrentResourceStrings(QueryBuilderResourceStringsEN);
@@ -472,7 +487,7 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
472487
/**
473488
* Returns if the fields combo at the root level is disabled.
474489
*/
475-
public get disableReturnFieldsChange(): boolean {
490+
public get disableReturnFieldsChange(): boolean {
476491

477492
return !this.selectedEntity || this.queryBuilder.disableReturnFieldsChange;
478493
}
@@ -519,11 +534,12 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
519534
}
520535

521536
constructor(public cdr: ChangeDetectorRef,
537+
public dragService: IgxQueryBuilderDragService,
522538
protected platform: PlatformUtil,
523-
protected el: ElementRef,
524539
private elRef: ElementRef,
525540
@Inject(LOCALE_ID) protected _localeId: string) {
526541
this.locale = this.locale || this._localeId;
542+
this.dragService.register(this, elRef);
527543
}
528544

529545
/**
@@ -842,7 +858,10 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
842858
}
843859
}
844860

845-
private deleteItem = (expressionItem: ExpressionItem, skipEmit: boolean = false) => {
861+
/**
862+
* @hidden @internal
863+
*/
864+
public deleteItem = (expressionItem: ExpressionItem, skipEmit: boolean = false) => {
846865
if (!expressionItem.parent) {
847866
this.rootGroup = null;
848867
this.currentGroup = null;
@@ -1025,16 +1044,13 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
10251044
this.deleteItem(expressionItem);
10261045
}
10271046

1028-
private focusChipAfterDrag = (index: number) => {
1029-
this._lastFocusedChipIndex = index;
1030-
this.focusEditedExpressionChip();
1031-
}
1032-
10331047
/**
10341048
* @hidden @internal
10351049
*/
1036-
public dragService: IgxQueryBuilderDragService = new IgxQueryBuilderDragService(this, this.el, this.deleteItem, this.focusChipAfterDrag);
1037-
1050+
public focusChipAfterDrag = (index: number) => {
1051+
this._lastFocusedChipIndex = index;
1052+
this.focusEditedExpressionChip();
1053+
}
10381054
/**
10391055
* @hidden @internal
10401056
*/
@@ -1136,8 +1152,8 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
11361152
expressionItem.expression.condition.name :
11371153
null;
11381154
this.searchValue.value = expressionItem.expression.searchVal instanceof Set ?
1139-
Array.from(expressionItem.expression.searchVal) :
1140-
expressionItem.expression.searchVal;
1155+
Array.from(expressionItem.expression.searchVal) :
1156+
expressionItem.expression.searchVal;
11411157

11421158
expressionItem.inEditMode = true;
11431159
this._editedExpression = expressionItem;
@@ -1172,7 +1188,7 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
11721188
input?.focus();
11731189
}
11741190

1175-
(this.editingInputs?.nativeElement.parentElement as HTMLElement)?.scrollIntoView({block: "nearest", inline: "nearest"});
1191+
(this.editingInputs?.nativeElement.parentElement as HTMLElement)?.scrollIntoView({ block: "nearest", inline: "nearest" });
11761192
}
11771193

11781194
/**
@@ -1312,7 +1328,7 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
13121328
* @hidden @internal
13131329
*/
13141330
public invokeClick(eventArgs: KeyboardEvent) {
1315-
if (!this.dragService.dropGhostChipNode && this.platform.isActivationKey(eventArgs)) {
1331+
if (!this.dragService.dropGhostExpression && this.platform.isActivationKey(eventArgs)) {
13161332
eventArgs.preventDefault();
13171333
(eventArgs.currentTarget as HTMLElement).click();
13181334
}
@@ -1544,7 +1560,7 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
15441560
return groupItem;
15451561
}
15461562

1547-
for (let i = 0 ; i < expressionTree.filteringOperands.length; i++) {
1563+
for (let i = 0; i < expressionTree.filteringOperands.length; i++) {
15481564
const expr = expressionTree.filteringOperands[i];
15491565

15501566
if (isTree(expr)) {

projects/igniteui-angular/src/lib/query-builder/query-builder.common.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export const QueryBuilderSelectors = {
6969
FILTER_TREE_EXPRESSION_CONTEXT_MENU: IGX_FILTER_TREE + '__expression-context-menu',
7070
FILTER_TREE_EXPRESSION_ITEM: IGX_FILTER_TREE + '__expression-item',
7171
FILTER_TREE_EXPRESSION_ITEM_DROP_GHOST: IGX_FILTER_TREE + '__expression-item-drop-ghost',
72+
FILTER_TREE_EXPRESSION_ITEM_KEYBOARD_GHOST: IGX_FILTER_TREE + '__expression-item-keyboard-ghost',
7273
FILTER_TREE_EXPRESSION_ITEM_GHOST: IGX_FILTER_TREE + '__expression-item-ghost',
7374
FILTER_TREE_EXPRESSION_SECTION: IGX_FILTER_TREE + '__expression-section',
7475

@@ -80,10 +81,4 @@ export const QueryBuilderSelectors = {
8081
QUERY_BUILDER_BODY: IGX_QUERY_BUILDER + '__main',
8182
QUERY_BUILDER_HEADER: IGX_QUERY_BUILDER + '__header',
8283
QUERY_BUILDER_TREE: IGX_QUERY_BUILDER + '-tree',
83-
84-
VIABLE_DROP_AREA:
85-
`.${IGX_FILTER_TREE}__expression-item[igxDrop]:not(.${IGX_FILTER_TREE + '__expression-item-drop-ghost'}),` + /*Condition chip*/
86-
`.${IGX_FILTER_TREE}__subquery:has([igxDrop]),` + /*Chip in edit*/
87-
`.${IGX_FILTER_TREE}__buttons > .igx-button[igxDrop]:first-of-type,` + /*Add Condition Button*/
88-
`.${IGX_FILTER_TREE}__expression-context-menu[igxDrop]` /*AND/OR group root*/
8984
}

0 commit comments

Comments
 (0)