Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { DragNDropValueObject } from 'common/models/elements/label-interfaces';
import { DropListComponent } from 'common/components/input-elements/drop-list/drop-list.component';
export class DropLogic {
static createDropListMock(dropListComp: DropListComponent): DropListMock {
return {
id: dropListComp.elementModel.id,
value: [...dropListComp.elementFormControl.value],
isSortList: dropListComp.elementModel.isSortList,
onlyOneItem: dropListComp.elementModel.onlyOneItem,
connectedTo: [...dropListComp.elementModel.connectedTo],
copyOnDrop: dropListComp.elementModel.copyOnDrop,
allowReplacement: dropListComp.elementModel.allowReplacement
};
}
static createDropListMocks(source: { [id: string]: DropListComponent }): { [id: string]: DropListMock } {
return Object.fromEntries(
Object.entries(source).map(([key, value]) => [
key,
DropLogic.createDropListMock(value)
])
);
}
static isDropAllowed(draggedItem: DragNDropValueObject,
sourceListID: string,
targetListID: string,
allLists: { [id: string]: DropListMock },
ignoreConnection: boolean = false): boolean {
const sourceList = allLists[sourceListID];
const targetList = allLists[targetListID];
return DropLogic.checkIsSourceList(sourceList, targetList) &&
DropLogic.checkConnected(sourceList, targetList, ignoreConnection) &&
DropLogic.checkOnlyOneItem(draggedItem, targetList, allLists) &&
DropLogic.checkAddForeignItemToCopyList(draggedItem, targetList);
}
/* Only allow drops in other lists, except for sortlists. */
private static checkIsSourceList(sourceList: DropListMock, targetList: DropListMock): boolean {
return (sourceList.id === targetList.id && sourceList.isSortList) ||
sourceList.id !== targetList.id;
}
/* Check list connection, sortlist is an exception since source and target can be the same. */
private static checkConnected(sourceList: DropListMock,
targetList: DropListMock, ignoreConnection: boolean = false): boolean {
return ignoreConnection ||
(sourceList.id === targetList.id && sourceList.isSortList) ||
sourceList.connectedTo.includes(targetList.id);
}
// ### Only One Item ###
/* Return false, when drop is not allowed */
private static checkOnlyOneItem(draggedItem: DragNDropValueObject, targetList: DropListMock,
allLists: { [id: string]: DropListMock }): boolean {
return !(targetList.onlyOneItem &&
targetList.value.length > 0 &&
!DropLogic.isReplace(draggedItem, targetList, allLists));
}
static isReplace(draggedItem: DragNDropValueObject, targetList: DropListMock,
allLists: { [id: string]: DropListMock }): boolean {
if (!(targetList.onlyOneItem && targetList.value.length === 1 && targetList.allowReplacement)) {
return false;
}
// Item is already in it's origin
if (targetList.value[0].originListID === targetList.id) {
return false;
}
const rest = targetList.value.splice(0, 1, draggedItem)[0];
return DropLogic.isDropAllowed(
rest,
targetList.id,
allLists[rest.originListID].id,
allLists,
true
);
}
// ### Copy List ###
static isPutBack(draggedItem: DragNDropValueObject, targetList: DropListMock): boolean {
return targetList.copyOnDrop && draggedItem.originListID === targetList.id;
}
/* Don't allow moving item into copy list that does not originate from there. */
private static checkAddForeignItemToCopyList(draggedItem: DragNDropValueObject | undefined,
targetList: DropListMock): boolean {
return !(targetList.copyOnDrop && draggedItem?.originListID !== targetList.id);
}
}
export interface DropListMock {
id: string;
value: DragNDropValueObject[];
isSortList: boolean;
onlyOneItem: boolean;
connectedTo: string[];
copyOnDrop: boolean;
allowReplacement: boolean;
}