Skip to content
Snippets Groups Projects
drop-logic.ts 4.01 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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;
    }