@progress/kendo-angular-treelist 13.0.0-develop.3 → 13.0.0-develop.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding-directives/base-binding.directive.d.ts +5 -1
- package/binding-directives/data-bound-tree-component.d.ts +9 -0
- package/binding-directives/flat-binding.directive.d.ts +14 -3
- package/binding-directives/hierarchy-binding.directive.d.ts +12 -3
- package/columns/column-base.d.ts +4 -0
- package/columns/rowreorder-column.component.d.ts +19 -0
- package/esm2020/binding-directives/base-binding.directive.mjs +9 -3
- package/esm2020/binding-directives/flat-binding.directive.mjs +56 -6
- package/esm2020/binding-directives/hierarchy-binding.directive.mjs +46 -6
- package/esm2020/columns/column-base.mjs +4 -0
- package/esm2020/columns/rowreorder-column.component.mjs +47 -0
- package/esm2020/index.mjs +2 -0
- package/esm2020/localization/messages.mjs +3 -1
- package/esm2020/package-metadata.mjs +2 -2
- package/esm2020/rendering/cell.component.mjs +47 -16
- package/esm2020/rendering/constants.mjs +4 -0
- package/esm2020/rendering/table-body.component.mjs +5 -3
- package/esm2020/row-reordering/flat-reorder.service.mjs +48 -0
- package/esm2020/row-reordering/hierarchical-reorder.service.mjs +55 -0
- package/esm2020/row-reordering/row-reorder.service.mjs +220 -0
- package/esm2020/row-reordering/types.mjs +5 -0
- package/esm2020/row-reordering/utils.mjs +129 -0
- package/esm2020/shared.module.mjs +8 -3
- package/esm2020/treelist.component.mjs +161 -23
- package/esm2020/treelist.module.mjs +71 -66
- package/fesm2015/progress-kendo-angular-treelist.mjs +808 -62
- package/fesm2020/progress-kendo-angular-treelist.mjs +799 -62
- package/index.d.ts +2 -0
- package/localization/messages.d.ts +5 -1
- package/package.json +16 -15
- package/rendering/cell.component.d.ts +6 -1
- package/rendering/constants.d.ts +4 -0
- package/row-reordering/flat-reorder.service.d.ts +16 -0
- package/row-reordering/hierarchical-reorder.service.d.ts +16 -0
- package/row-reordering/row-reorder.service.d.ts +61 -0
- package/row-reordering/types.d.ts +39 -0
- package/row-reordering/utils.d.ts +85 -0
- package/schematics/ngAdd/index.js +3 -3
- package/shared.module.d.ts +5 -4
- package/treelist.component.d.ts +42 -2
- package/treelist.module.d.ts +68 -66
|
@@ -4,34 +4,38 @@
|
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
5
|
import { Component, HostBinding, Input } from '@angular/core';
|
|
6
6
|
import { EditService } from '../editing/edit.service';
|
|
7
|
-
import { isSpanColumn, isCheckboxColumn } from '../columns/column-base';
|
|
7
|
+
import { isSpanColumn, isCheckboxColumn, isRowReorderColumn } from '../columns/column-base';
|
|
8
8
|
import { isColumnComponent } from '../columns/column.component';
|
|
9
9
|
import { columnsToRender } from "../columns/column-common";
|
|
10
10
|
import { isNullOrEmptyString, extractFormat, isColumnEditable } from '../utils';
|
|
11
11
|
import { FocusGroup } from '../navigation/focus-group';
|
|
12
|
-
import { caretAltDownIcon, caretAltRightIcon } from '@progress/kendo-svg-icons';
|
|
12
|
+
import { caretAltDownIcon, caretAltRightIcon, reorderIcon } from '@progress/kendo-svg-icons';
|
|
13
|
+
import { LocalizationService } from "@progress/kendo-angular-l10n";
|
|
13
14
|
import * as i0 from "@angular/core";
|
|
14
15
|
import * as i1 from "../editing/edit.service";
|
|
15
|
-
import * as i2 from "
|
|
16
|
-
import * as i3 from "
|
|
17
|
-
import * as i4 from "@progress/kendo-angular-
|
|
18
|
-
import * as i5 from "@progress/kendo-angular-
|
|
19
|
-
import * as i6 from "@angular
|
|
20
|
-
import * as i7 from "
|
|
21
|
-
import * as i8 from "
|
|
22
|
-
import * as i9 from "
|
|
23
|
-
import * as i10 from "./common/
|
|
16
|
+
import * as i2 from "@progress/kendo-angular-l10n";
|
|
17
|
+
import * as i3 from "../navigation/focus-group";
|
|
18
|
+
import * as i4 from "@progress/kendo-angular-icons";
|
|
19
|
+
import * as i5 from "@progress/kendo-angular-inputs";
|
|
20
|
+
import * as i6 from "@progress/kendo-angular-dateinputs";
|
|
21
|
+
import * as i7 from "@angular/common";
|
|
22
|
+
import * as i8 from "../navigation/focusable.directive";
|
|
23
|
+
import * as i9 from "@angular/forms";
|
|
24
|
+
import * as i10 from "./common/level-items.pipe";
|
|
25
|
+
import * as i11 from "./common/field-accessor.pipe";
|
|
24
26
|
/**
|
|
25
27
|
* @hidden
|
|
26
28
|
*/
|
|
27
29
|
export class CellComponent {
|
|
28
|
-
constructor(editService, focusGroup) {
|
|
30
|
+
constructor(editService, localization, focusGroup) {
|
|
29
31
|
this.editService = editService;
|
|
32
|
+
this.localization = localization;
|
|
30
33
|
this.focusGroup = focusGroup;
|
|
31
34
|
this.isNew = false;
|
|
32
35
|
this.level = 0;
|
|
33
36
|
this.caretAltDownIcon = caretAltDownIcon;
|
|
34
37
|
this.caretAltRightIcon = caretAltRightIcon;
|
|
38
|
+
this.reorderIcon = reorderIcon;
|
|
35
39
|
this.cellContext = {};
|
|
36
40
|
this._templateContext = {};
|
|
37
41
|
this._editTemplateContext = {};
|
|
@@ -47,6 +51,12 @@ export class CellComponent {
|
|
|
47
51
|
get textNoWrapClass() {
|
|
48
52
|
return this.column.expandable;
|
|
49
53
|
}
|
|
54
|
+
get dragHandleCellClass() {
|
|
55
|
+
return isRowReorderColumn(this.column);
|
|
56
|
+
}
|
|
57
|
+
get dragRowHandleLabel() {
|
|
58
|
+
return isRowReorderColumn(this.column) ? this.localization.get('dragRowHandleLabel') : undefined;
|
|
59
|
+
}
|
|
50
60
|
set viewItem(value) {
|
|
51
61
|
this._viewItem = value;
|
|
52
62
|
this.cellContext.viewItem = this.viewItem;
|
|
@@ -114,8 +124,8 @@ export class CellComponent {
|
|
|
114
124
|
context.rowIndex = this.viewItem.rowIndex;
|
|
115
125
|
}
|
|
116
126
|
}
|
|
117
|
-
CellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellComponent, deps: [{ token: i1.EditService }, { token: i2.FocusGroup }], target: i0.ɵɵFactoryTarget.Component });
|
|
118
|
-
CellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: CellComponent, selector: "[kendoTreeListCell]", inputs: { column: "column", columnIndex: "columnIndex", isNew: "isNew", level: "level", hasChildren: "hasChildren", isExpanded: "isExpanded", loading: "loading", expandIcons: "expandIcons", selected: "selected", dataItem: "dataItem", viewItem: "viewItem" }, host: { properties: { "class.k-command-cell": "this.commandCellClass", "class.k-checkbox-cell": "this.isCheckboxColumn", "class.k-text-nowrap": "this.textNoWrapClass" } }, ngImport: i0, template: `
|
|
127
|
+
CellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellComponent, deps: [{ token: i1.EditService }, { token: i2.LocalizationService }, { token: i3.FocusGroup }], target: i0.ɵɵFactoryTarget.Component });
|
|
128
|
+
CellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: CellComponent, selector: "[kendoTreeListCell]", inputs: { column: "column", columnIndex: "columnIndex", isNew: "isNew", level: "level", hasChildren: "hasChildren", isExpanded: "isExpanded", loading: "loading", expandIcons: "expandIcons", selected: "selected", dataItem: "dataItem", viewItem: "viewItem" }, host: { properties: { "class.k-command-cell": "this.commandCellClass", "class.k-checkbox-cell": "this.isCheckboxColumn", "class.k-text-nowrap": "this.textNoWrapClass", "class.k-drag-cell": "this.dragHandleCellClass", "class.k-touch-action-none": "this.dragHandleCellClass", "attr.aria-label": "this.dragRowHandleLabel" } }, ngImport: i0, template: `
|
|
119
129
|
<ng-container [ngSwitch]="isEdited">
|
|
120
130
|
<ng-container *ngSwitchCase="false">
|
|
121
131
|
<ng-container *ngIf="column.expandable">
|
|
@@ -144,6 +154,12 @@ CellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
|
|
|
144
154
|
class="k-checkbox k-checkbox-md k-rounded-md"
|
|
145
155
|
[checked]="selected" />
|
|
146
156
|
</ng-template>
|
|
157
|
+
<ng-container *ngIf="column.isRowReorderColumn && !isNew">
|
|
158
|
+
<kendo-icon-wrapper
|
|
159
|
+
name="reorder"
|
|
160
|
+
[svgIcon]="reorderIcon">
|
|
161
|
+
</kendo-icon-wrapper>
|
|
162
|
+
</ng-container>
|
|
147
163
|
</ng-container>
|
|
148
164
|
<ng-container *ngSwitchCase="true">
|
|
149
165
|
<ng-container
|
|
@@ -184,7 +200,7 @@ CellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
|
|
|
184
200
|
</ng-container>
|
|
185
201
|
</ng-container>
|
|
186
202
|
</ng-container>
|
|
187
|
-
`, isInline: true, components: [{ type:
|
|
203
|
+
`, isInline: true, components: [{ type: i4.IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass"], exportAs: ["kendoIconWrapper"] }, { type: i5.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode"], outputs: ["valueChange", "focus", "blur"], exportAs: ["kendoNumericTextBox"] }, { type: i6.DatePickerComponent, selector: "kendo-datepicker", inputs: ["focusableId", "cellTemplate", "monthCellTemplate", "yearCellTemplate", "decadeCellTemplate", "centuryCellTemplate", "weekNumberTemplate", "headerTitleTemplate", "navigationItemTemplate", "activeView", "bottomView", "topView", "calendarType", "animateCalendarNavigation", "disabled", "readonly", "readOnlyInput", "popupSettings", "navigation", "min", "max", "incompleteDateValidation", "focusedDate", "value", "format", "twoDigitYearMax", "formatPlaceholder", "placeholder", "tabindex", "tabIndex", "disabledDates", "title", "subtitle", "rangeValidation", "disabledDatesValidation", "weekNumber", "size", "rounded", "fillMode", "adaptiveMode"], outputs: ["valueChange", "focus", "blur", "open", "close"], exportAs: ["kendo-datepicker"] }], directives: [{ type: i7.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i7.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i8.FocusableDirective, selector: "[kendoTreeListFocusable],\n [kendoTreeListAddCommand],\n [kendoTreeListEditCommand],\n [kendoTreeListRemoveCommand],\n [kendoTreeListSaveCommand],\n [kendoTreeListCancelCommand]\n ", inputs: ["kendoTreeListFocusable", "enabled", "kendoTreeListAddCommand", "kendoTreeListEditCommand", "kendoTreeListRemoveCommand", "kendoTreeListSaveCommand", "kendoTreeListCancelCommand"] }, { type: i9.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i9.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { type: i9.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { type: i7.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { type: i9.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }], pipes: { "levelItems": i10.LevelItemsPipe, "valueOf": i11.FieldAccessorPipe } });
|
|
188
204
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: CellComponent, decorators: [{
|
|
189
205
|
type: Component,
|
|
190
206
|
args: [{
|
|
@@ -218,6 +234,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
218
234
|
class="k-checkbox k-checkbox-md k-rounded-md"
|
|
219
235
|
[checked]="selected" />
|
|
220
236
|
</ng-template>
|
|
237
|
+
<ng-container *ngIf="column.isRowReorderColumn && !isNew">
|
|
238
|
+
<kendo-icon-wrapper
|
|
239
|
+
name="reorder"
|
|
240
|
+
[svgIcon]="reorderIcon">
|
|
241
|
+
</kendo-icon-wrapper>
|
|
242
|
+
</ng-container>
|
|
221
243
|
</ng-container>
|
|
222
244
|
<ng-container *ngSwitchCase="true">
|
|
223
245
|
<ng-container
|
|
@@ -260,7 +282,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
260
282
|
</ng-container>
|
|
261
283
|
`
|
|
262
284
|
}]
|
|
263
|
-
}], ctorParameters: function () { return [{ type: i1.EditService }, { type: i2.FocusGroup }]; }, propDecorators: { commandCellClass: [{
|
|
285
|
+
}], ctorParameters: function () { return [{ type: i1.EditService }, { type: i2.LocalizationService }, { type: i3.FocusGroup }]; }, propDecorators: { commandCellClass: [{
|
|
264
286
|
type: HostBinding,
|
|
265
287
|
args: ['class.k-command-cell']
|
|
266
288
|
}], isCheckboxColumn: [{
|
|
@@ -269,6 +291,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
|
|
|
269
291
|
}], textNoWrapClass: [{
|
|
270
292
|
type: HostBinding,
|
|
271
293
|
args: ['class.k-text-nowrap']
|
|
294
|
+
}], dragHandleCellClass: [{
|
|
295
|
+
type: HostBinding,
|
|
296
|
+
args: ['class.k-drag-cell']
|
|
297
|
+
}, {
|
|
298
|
+
type: HostBinding,
|
|
299
|
+
args: ['class.k-touch-action-none']
|
|
300
|
+
}], dragRowHandleLabel: [{
|
|
301
|
+
type: HostBinding,
|
|
302
|
+
args: ['attr.aria-label']
|
|
272
303
|
}], column: [{
|
|
273
304
|
type: Input
|
|
274
305
|
}], columnIndex: [{
|
|
@@ -18,7 +18,7 @@ import { Keys } from '@progress/kendo-angular-common';
|
|
|
18
18
|
import { defaultTrackBy } from '../common/default-track-by';
|
|
19
19
|
import { ExpandStateService } from '../expand-state/expand-state.service';
|
|
20
20
|
import { SelectionService } from '../selection/selection.service';
|
|
21
|
-
import { NON_DATA_CELL_CLASSES, NON_DATA_ROW_CLASSES, IGNORE_CONTAINER_CLASSES, ICON_CLASS, EMPTY_ICON_CLASS } from './constants';
|
|
21
|
+
import { NON_DATA_CELL_CLASSES, NON_DATA_ROW_CLASSES, IGNORE_CONTAINER_CLASSES, ICON_CLASS, EMPTY_ICON_CLASS, DRAG_HANDLE_CLASS } from './constants';
|
|
22
22
|
import * as i0 from "@angular/core";
|
|
23
23
|
import * as i1 from "../data/change-notification.service";
|
|
24
24
|
import * as i2 from "../editing/edit.service";
|
|
@@ -213,8 +213,10 @@ export class TableBodyComponent {
|
|
|
213
213
|
clickHandler(eventArg) {
|
|
214
214
|
const target = eventArg.target;
|
|
215
215
|
const { cell, row } = this.targetElements(target);
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
const forbiddenCellClasses = NON_DATA_CELL_CLASSES.concat(` ${DRAG_HANDLE_CLASS}`);
|
|
217
|
+
const isValidCell = cell ? !hasClasses(cell, forbiddenCellClasses) : false;
|
|
218
|
+
const isValidRow = row ? !hasClasses(row, NON_DATA_ROW_CLASSES) : false;
|
|
219
|
+
if (isValidRow && isValidCell) {
|
|
218
220
|
if (this.expandClick(eventArg, row) || this.checkboxClick(cell, row, eventArg)) {
|
|
219
221
|
return;
|
|
220
222
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2023 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { Injectable } from "@angular/core";
|
|
6
|
+
import { RowReorderService } from './row-reorder.service';
|
|
7
|
+
import { isPresent } from "../utils";
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
/**
|
|
10
|
+
* @hidden
|
|
11
|
+
*/
|
|
12
|
+
export class FlatRowReorderService extends RowReorderService {
|
|
13
|
+
isOverChild(targetItem) {
|
|
14
|
+
const { draggedRows } = this.rowReorderArgs(this.dragTarget, this.dropTarget, this.view);
|
|
15
|
+
const draggedItem = draggedRows[0].dataItem;
|
|
16
|
+
const hasParent = isPresent(targetItem[this.parentIdField]);
|
|
17
|
+
const sameParents = draggedItem[this.parentIdField] === targetItem[this.parentIdField];
|
|
18
|
+
if (!hasParent || sameParents) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if (targetItem && targetItem.hasOwnProperty(this.parentIdField)) {
|
|
22
|
+
if (draggedItem[this.idField] === targetItem[this.parentIdField]) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
const parent = this.data.find(i => i[this.idField] === targetItem[this.parentIdField]);
|
|
26
|
+
if (parent) {
|
|
27
|
+
return this.isOverChild(parent);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
reorderRows(ev, collection) {
|
|
32
|
+
const { draggedRows, dropTargetRow } = ev;
|
|
33
|
+
const draggedDataItem = draggedRows[0].dataItem;
|
|
34
|
+
const dropTargetDataItem = dropTargetRow.dataItem;
|
|
35
|
+
let dropTargetIdx = collection.indexOf(dropTargetDataItem);
|
|
36
|
+
const draggedItemIdx = collection.indexOf(draggedDataItem);
|
|
37
|
+
collection.splice(draggedItemIdx, 1);
|
|
38
|
+
if (ev.dropPosition === 'after' && dropTargetIdx < draggedItemIdx) {
|
|
39
|
+
dropTargetIdx++;
|
|
40
|
+
}
|
|
41
|
+
collection.splice(dropTargetIdx, 0, draggedDataItem);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
FlatRowReorderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FlatRowReorderService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
45
|
+
FlatRowReorderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FlatRowReorderService });
|
|
46
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FlatRowReorderService, decorators: [{
|
|
47
|
+
type: Injectable
|
|
48
|
+
}] });
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2023 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { Injectable } from "@angular/core";
|
|
6
|
+
import { RowReorderService } from './row-reorder.service';
|
|
7
|
+
import { isPresent } from "../utils";
|
|
8
|
+
import { dropPosition, findParent } from "./utils";
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
/**
|
|
11
|
+
* @hidden
|
|
12
|
+
*/
|
|
13
|
+
export class HierarchicalRowReorderService extends RowReorderService {
|
|
14
|
+
isOverChild(targetItem) {
|
|
15
|
+
const { draggedRows } = this.rowReorderArgs(this.dragTarget, this.dropTarget, this.view);
|
|
16
|
+
const draggedItem = draggedRows[0].dataItem;
|
|
17
|
+
const hasChildren = isPresent(draggedItem[this.childrenField]) && draggedItem[this.childrenField].length > 0;
|
|
18
|
+
if (!hasChildren) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if (targetItem && draggedItem.hasOwnProperty(this.childrenField)) {
|
|
22
|
+
if (draggedItem[this.childrenField].includes(targetItem)) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
const parent = findParent(this.data, targetItem, this.childrenField);
|
|
26
|
+
if (parent) {
|
|
27
|
+
return this.isOverChild(parent);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
reorderRows(ev, collection, field) {
|
|
33
|
+
const draggedItem = ev.draggedRows[0].dataItem;
|
|
34
|
+
const dropTargetItem = ev.dropTargetRow.dataItem;
|
|
35
|
+
const draggedItemParent = findParent(collection, draggedItem, field);
|
|
36
|
+
const dropTargetParent = findParent(collection, dropTargetItem, field);
|
|
37
|
+
const draggedItemIdx = draggedItemParent ? draggedItemParent[field].indexOf(draggedItem) : collection.indexOf(draggedItem);
|
|
38
|
+
let dropTargetItemIdx = dropTargetParent ? dropTargetParent[field].indexOf(dropTargetItem) : collection.indexOf(dropTargetItem);
|
|
39
|
+
if (ev.dropPosition === dropPosition.after && dropTargetItemIdx < draggedItemIdx) {
|
|
40
|
+
dropTargetItemIdx++;
|
|
41
|
+
}
|
|
42
|
+
draggedItemParent ? draggedItemParent[field].splice(draggedItemIdx, 1) : collection.splice(draggedItemIdx, 1);
|
|
43
|
+
if (ev.dropPosition !== dropPosition.over) {
|
|
44
|
+
dropTargetParent ? dropTargetParent[field].splice(dropTargetItemIdx, 0, draggedItem) : collection.splice(dropTargetItemIdx, 0, draggedItem);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
dropTargetItem[field].unshift(draggedItem);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
HierarchicalRowReorderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HierarchicalRowReorderService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
52
|
+
HierarchicalRowReorderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HierarchicalRowReorderService });
|
|
53
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: HierarchicalRowReorderService, decorators: [{
|
|
54
|
+
type: Injectable
|
|
55
|
+
}] });
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2023 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { EventEmitter, Injectable, Output, Renderer2 } from '@angular/core';
|
|
6
|
+
import { isDocumentAvailable, isPresent } from '@progress/kendo-angular-common';
|
|
7
|
+
import { getOffset, isNextSibling, isPreviousSibling, dropPosition, hintIcons, hintSVGIcons, hintClasses, hintStyles, dropIndicatorClasses, dropIndicatorStyles, defaultSelectors, rowIndexAttr } from './utils';
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
/**
|
|
10
|
+
* @hidden
|
|
11
|
+
*/
|
|
12
|
+
export class RowReorderService {
|
|
13
|
+
constructor(renderer) {
|
|
14
|
+
this.renderer = renderer;
|
|
15
|
+
this.defaultSelectors = defaultSelectors;
|
|
16
|
+
this.dragTarget = null;
|
|
17
|
+
this.dropTarget = null;
|
|
18
|
+
this.lastDropPosition = dropPosition.forbidden;
|
|
19
|
+
this.hintElement = null;
|
|
20
|
+
this.rowReorder = new EventEmitter();
|
|
21
|
+
}
|
|
22
|
+
press(ev) {
|
|
23
|
+
this.dragTarget = ev.dragTarget;
|
|
24
|
+
this.offsetY = ev.dragEvent.offsetY;
|
|
25
|
+
}
|
|
26
|
+
dragStart() {
|
|
27
|
+
this.createDropIndicator();
|
|
28
|
+
}
|
|
29
|
+
drag(ev) {
|
|
30
|
+
if (isPresent(ev.hintElement) && !isPresent(this.hintElement)) {
|
|
31
|
+
this.hintElement = ev.hintElement;
|
|
32
|
+
this.decorateHint();
|
|
33
|
+
}
|
|
34
|
+
const position = {
|
|
35
|
+
x: ev.dragEvent.clientX,
|
|
36
|
+
y: ev.dragEvent.clientY - this.offsetY
|
|
37
|
+
};
|
|
38
|
+
if (isPresent(this.hintElement)) {
|
|
39
|
+
this.renderer.setStyle(this.hintElement, 'left', `${position.x}px`);
|
|
40
|
+
this.renderer.setStyle(this.hintElement, 'top', `${position.y}px`);
|
|
41
|
+
}
|
|
42
|
+
this.positionDropIndicator(ev);
|
|
43
|
+
}
|
|
44
|
+
dragEnter(ev) {
|
|
45
|
+
this.dropTarget = ev.dropTarget;
|
|
46
|
+
this.view = ev.dragData;
|
|
47
|
+
}
|
|
48
|
+
dragLeave() {
|
|
49
|
+
this.dropTarget = null;
|
|
50
|
+
this.lastDropPosition === dropPosition.forbidden && this.hide();
|
|
51
|
+
}
|
|
52
|
+
dragEnd() {
|
|
53
|
+
this.destroyDropIndicator();
|
|
54
|
+
this.dragTarget = null;
|
|
55
|
+
this.dropTarget = null;
|
|
56
|
+
this.hintElement = null;
|
|
57
|
+
}
|
|
58
|
+
drop() {
|
|
59
|
+
this.destroyDropIndicator();
|
|
60
|
+
const rowReorderArgs = this.rowReorderArgs(this.dragTarget, this.dropTarget, this.view);
|
|
61
|
+
this.rowReorder.emit(rowReorderArgs);
|
|
62
|
+
}
|
|
63
|
+
get hintIcon() {
|
|
64
|
+
return hintIcons[this.lastDropPosition];
|
|
65
|
+
}
|
|
66
|
+
get hintSVGIcon() {
|
|
67
|
+
return hintSVGIcons[this.lastDropPosition];
|
|
68
|
+
}
|
|
69
|
+
getDefaultHintText(columns, data) {
|
|
70
|
+
let hintText = '';
|
|
71
|
+
const columnFieldsArray = columns
|
|
72
|
+
.toArray()
|
|
73
|
+
.filter(column => !column.hidden && isPresent(column.field))
|
|
74
|
+
.map(column => column.field);
|
|
75
|
+
const draggedDragRow = this.getDragRowPerElement(this.dragTarget, data);
|
|
76
|
+
const draggedDataItem = draggedDragRow?.dataItem;
|
|
77
|
+
isPresent(draggedDataItem) && columnFieldsArray.forEach(column => {
|
|
78
|
+
const columnValue = draggedDataItem[column];
|
|
79
|
+
isPresent(columnValue) ? hintText += `${columnValue} ` : null;
|
|
80
|
+
});
|
|
81
|
+
return hintText.trim();
|
|
82
|
+
}
|
|
83
|
+
rowReorderArgs(dragRow, dropRow, data) {
|
|
84
|
+
const dragRowData = this.getDragRowPerElement(dragRow, data);
|
|
85
|
+
const dropRowData = this.getDragRowPerElement(dropRow, data);
|
|
86
|
+
return {
|
|
87
|
+
draggedRows: [dragRowData],
|
|
88
|
+
dropTargetRow: dropRowData,
|
|
89
|
+
dropPosition: this.lastDropPosition
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
isOverChild(_item) { return false; }
|
|
93
|
+
reorderRows(_ev, _collection, _field) { }
|
|
94
|
+
get parentIdField() {
|
|
95
|
+
return this.bindingDirective.parentIdField;
|
|
96
|
+
}
|
|
97
|
+
get idField() {
|
|
98
|
+
return this.bindingDirective.idField;
|
|
99
|
+
}
|
|
100
|
+
get childrenField() {
|
|
101
|
+
return this.bindingDirective.childrenField;
|
|
102
|
+
}
|
|
103
|
+
get data() {
|
|
104
|
+
return this.bindingDirective.data;
|
|
105
|
+
}
|
|
106
|
+
getDragRowPerElement(row, data) {
|
|
107
|
+
let rowIndex = row?.getAttribute(rowIndexAttr);
|
|
108
|
+
rowIndex = rowIndex ? parseInt(rowIndex, 10) : -1;
|
|
109
|
+
const dataItem = rowIndex === -1 ? null : data?.at(rowIndex)?.data;
|
|
110
|
+
return {
|
|
111
|
+
dataItem,
|
|
112
|
+
rowIndex,
|
|
113
|
+
element: row
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
createDropIndicator() {
|
|
117
|
+
if (!isDocumentAvailable()) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
this.dropIndicator = document.createElement('div');
|
|
121
|
+
this.decorateDropIndicator();
|
|
122
|
+
this.dropIndicator.innerHTML = `
|
|
123
|
+
<div class="k-drop-hint-start"></div>
|
|
124
|
+
<div class="k-drop-hint-line"></div>
|
|
125
|
+
`;
|
|
126
|
+
document.body.appendChild(this.dropIndicator);
|
|
127
|
+
this.hide();
|
|
128
|
+
}
|
|
129
|
+
destroyDropIndicator() {
|
|
130
|
+
if (!isDocumentAvailable()) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
;
|
|
134
|
+
if (this.dropIndicator && this.dropIndicator.parentElement) {
|
|
135
|
+
document.body.removeChild(this.dropIndicator);
|
|
136
|
+
this.dropIndicator = null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
decorateHint() {
|
|
140
|
+
hintClasses.forEach(className => this.renderer.addClass(this.hintElement, className));
|
|
141
|
+
Object.keys(hintStyles)
|
|
142
|
+
.forEach(style => this.renderer.setStyle(this.hintElement, style, hintStyles[style]));
|
|
143
|
+
}
|
|
144
|
+
positionDropIndicator(ev) {
|
|
145
|
+
this.lastDropPosition = this.getDropPosition(ev.dragEvent);
|
|
146
|
+
this.updateDropIndicatorPosition();
|
|
147
|
+
}
|
|
148
|
+
decorateDropIndicator() {
|
|
149
|
+
dropIndicatorClasses.forEach(className => this.renderer.addClass(this.dropIndicator, className));
|
|
150
|
+
Object.keys(dropIndicatorStyles)
|
|
151
|
+
.forEach(style => this.renderer.setStyle(this.dropIndicator, style, dropIndicatorStyles[style]));
|
|
152
|
+
}
|
|
153
|
+
getDropPosition(e) {
|
|
154
|
+
if (this.dropTarget === this.dragTarget || !isPresent(this.dropTarget)) {
|
|
155
|
+
return dropPosition.forbidden;
|
|
156
|
+
}
|
|
157
|
+
;
|
|
158
|
+
const itemViewPortCoords = this.dropTarget.getBoundingClientRect();
|
|
159
|
+
const itemDivisionsCount = 3;
|
|
160
|
+
const itemDivisionHeight = itemViewPortCoords.height / itemDivisionsCount;
|
|
161
|
+
const { dropTargetRow } = this.rowReorderArgs(this.dragTarget, this.dropTarget, this.view);
|
|
162
|
+
const pointerPosition = e.clientY;
|
|
163
|
+
const itemTop = itemViewPortCoords.top;
|
|
164
|
+
let currentDropPosition = null;
|
|
165
|
+
if (pointerPosition <= itemTop + itemDivisionHeight) {
|
|
166
|
+
currentDropPosition = dropPosition.before;
|
|
167
|
+
}
|
|
168
|
+
else if (pointerPosition >= itemTop + itemViewPortCoords.height - itemDivisionHeight) {
|
|
169
|
+
currentDropPosition = dropPosition.after;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
currentDropPosition = dropPosition.over;
|
|
173
|
+
}
|
|
174
|
+
if (currentDropPosition === dropPosition.before && isNextSibling(this.dropTarget, this.dragTarget)) {
|
|
175
|
+
currentDropPosition = dropPosition.forbidden;
|
|
176
|
+
}
|
|
177
|
+
else if (currentDropPosition === dropPosition.after && isPreviousSibling(this.dropTarget, this.dragTarget)) {
|
|
178
|
+
currentDropPosition = dropPosition.forbidden;
|
|
179
|
+
}
|
|
180
|
+
if (this.isOverChild(dropTargetRow.dataItem)) {
|
|
181
|
+
currentDropPosition = dropPosition.forbidden;
|
|
182
|
+
}
|
|
183
|
+
return currentDropPosition;
|
|
184
|
+
}
|
|
185
|
+
updateDropIndicatorPosition() {
|
|
186
|
+
if (this.shouldHideDropIndicator() || !this.dropTarget) {
|
|
187
|
+
this.hide();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
this.show();
|
|
191
|
+
const destinationItemOffset = getOffset(this.dropTarget);
|
|
192
|
+
let indicatorOffsetTop = destinationItemOffset.top;
|
|
193
|
+
const indicatorOffsetLeft = destinationItemOffset.left + this.dropIndicator.offsetWidth / 2;
|
|
194
|
+
if (this.lastDropPosition === dropPosition.after) {
|
|
195
|
+
indicatorOffsetTop += this.dropTarget.offsetHeight;
|
|
196
|
+
}
|
|
197
|
+
this.renderer.setStyle(this.dropIndicator, 'left', `${indicatorOffsetLeft}px`);
|
|
198
|
+
this.renderer.setStyle(this.dropIndicator, 'top', `${indicatorOffsetTop}px`);
|
|
199
|
+
}
|
|
200
|
+
shouldHideDropIndicator() {
|
|
201
|
+
return this.lastDropPosition === dropPosition.forbidden || this.lastDropPosition === dropPosition.over;
|
|
202
|
+
}
|
|
203
|
+
hide() {
|
|
204
|
+
if (isPresent(this.dropIndicator)) {
|
|
205
|
+
this.renderer.setStyle(this.dropIndicator, 'display', 'none');
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
show() {
|
|
209
|
+
if (isPresent(this.dropIndicator)) {
|
|
210
|
+
this.renderer.removeStyle(this.dropIndicator, 'display');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
RowReorderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: RowReorderService, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
215
|
+
RowReorderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: RowReorderService });
|
|
216
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: RowReorderService, decorators: [{
|
|
217
|
+
type: Injectable
|
|
218
|
+
}], ctorParameters: function () { return [{ type: i0.Renderer2 }]; }, propDecorators: { rowReorder: [{
|
|
219
|
+
type: Output
|
|
220
|
+
}] } });
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2023 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2023 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { cancelIcon, insertMiddleIcon, plusIcon } from '@progress/kendo-svg-icons';
|
|
6
|
+
/**
|
|
7
|
+
* @hidden
|
|
8
|
+
*/
|
|
9
|
+
export const isNextSibling = (dropTarget, dragTarget) => dropTarget === dragTarget.nextElementSibling;
|
|
10
|
+
/**
|
|
11
|
+
* @hidden
|
|
12
|
+
*/
|
|
13
|
+
export const isPreviousSibling = (dropTarget, dragTarget) => dropTarget === dragTarget.previousElementSibling;
|
|
14
|
+
/**
|
|
15
|
+
* @hidden
|
|
16
|
+
*/
|
|
17
|
+
export function getOffset(element) {
|
|
18
|
+
const { clientTop, clientLeft } = getDocument(element);
|
|
19
|
+
const { pageYOffset, pageXOffset } = getWindow(element);
|
|
20
|
+
const { top, left } = element.getBoundingClientRect();
|
|
21
|
+
return {
|
|
22
|
+
top: top + pageYOffset - clientTop,
|
|
23
|
+
left: left + pageXOffset - clientLeft
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
;
|
|
27
|
+
/**
|
|
28
|
+
* @hidden
|
|
29
|
+
*/
|
|
30
|
+
export const hintIcons = {
|
|
31
|
+
forbidden: 'cancel',
|
|
32
|
+
before: 'insert-middle',
|
|
33
|
+
after: 'insert-middle',
|
|
34
|
+
over: 'plus'
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* @hidden
|
|
38
|
+
*/
|
|
39
|
+
export const hintSVGIcons = {
|
|
40
|
+
forbidden: cancelIcon,
|
|
41
|
+
before: insertMiddleIcon,
|
|
42
|
+
after: insertMiddleIcon,
|
|
43
|
+
over: plusIcon
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* @hidden
|
|
47
|
+
*/
|
|
48
|
+
export const dropPosition = {
|
|
49
|
+
forbidden: 'forbidden',
|
|
50
|
+
before: 'before',
|
|
51
|
+
after: 'after',
|
|
52
|
+
over: 'over'
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* @hidden
|
|
56
|
+
*/
|
|
57
|
+
export const hintStyles = {
|
|
58
|
+
zIndex: '20000',
|
|
59
|
+
display: 'flex',
|
|
60
|
+
position: 'fixed'
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* @hidden
|
|
64
|
+
*/
|
|
65
|
+
export const hintClasses = ['k-drag-clue', 'k-reorder-clue'];
|
|
66
|
+
/**
|
|
67
|
+
* @hidden
|
|
68
|
+
*/
|
|
69
|
+
export const dropIndicatorStyles = {
|
|
70
|
+
zIndex: '19000',
|
|
71
|
+
position: 'absolute'
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* @hidden
|
|
75
|
+
*/
|
|
76
|
+
export const dropIndicatorClasses = ['k-drop-hint', 'k-drop-hint-h'];
|
|
77
|
+
/**
|
|
78
|
+
* @hidden
|
|
79
|
+
*/
|
|
80
|
+
export const defaultSelectors = {
|
|
81
|
+
handle: '.k-table-td.k-drag-cell',
|
|
82
|
+
dragTarget: '.k-table-row[data-treelist-view-index]',
|
|
83
|
+
dropTarget: '.k-table-row[data-treelist-view-index]'
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* @hidden
|
|
87
|
+
*/
|
|
88
|
+
export const rowIndexAttr = 'data-treelist-view-index';
|
|
89
|
+
/**
|
|
90
|
+
* @hidden
|
|
91
|
+
*/
|
|
92
|
+
export const findParent = (collection, searchItem, field) => {
|
|
93
|
+
let parent = null;
|
|
94
|
+
for (const item of collection) {
|
|
95
|
+
if (searchItem === item) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const checked = [];
|
|
99
|
+
const queue = [];
|
|
100
|
+
queue.push(item);
|
|
101
|
+
while (queue.length !== 0) {
|
|
102
|
+
const current = queue.shift();
|
|
103
|
+
if (!current) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
checked.push(current);
|
|
107
|
+
if (current === searchItem) {
|
|
108
|
+
return item;
|
|
109
|
+
}
|
|
110
|
+
if (current.hasOwnProperty(field)) {
|
|
111
|
+
current[field].forEach(node => {
|
|
112
|
+
if (checked.indexOf(node) === -1) {
|
|
113
|
+
checked.push(node);
|
|
114
|
+
queue.push(node);
|
|
115
|
+
if (node === searchItem) {
|
|
116
|
+
parent = current;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (parent) {
|
|
123
|
+
return parent;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const getDocument = element => element?.ownerDocument.documentElement;
|
|
129
|
+
const getWindow = element => element?.ownerDocument.defaultView;
|