Skip to content
Snippets Groups Projects
drop-list.ts 6.37 KiB
Newer Older
import { Type } from '@angular/core';
  InputElement, InputElementProperties, UIElementType, UIElementValue
} from 'common/models/elements/element';
import { ElementComponent } from 'common/directives/element-component.directive';
rhenck's avatar
rhenck committed
import { DropListComponent } from 'common/components/input-elements/drop-list/drop-list.component';
import { VariableInfo, VariableValue } from '@iqb/responses';
import { DragNDropValueObject } from 'common/models/elements/label-interfaces';
rhenck's avatar
rhenck committed
  BasicStyles, PropertyGroupGenerators
} from 'common/models/elements/property-group-interfaces';
rhenck's avatar
rhenck committed
import { environment } from 'common/environment';
import { InstantiationEror } from 'common/util/errors';
export class DropListElement extends InputElement implements DropListProperties {
  type: UIElementType = 'drop-list';
  value: DragNDropValueObject[];
rhenck's avatar
rhenck committed
  isSortList: boolean = false;
  onlyOneItem: boolean = false;
  connectedTo: string[] = [];
  copyOnDrop: boolean = false;
  allowReplacement: boolean = false;
rhenck's avatar
rhenck committed
  orientation: 'vertical' | 'horizontal' | 'flex' = 'vertical'; // TODO besser floating
rhenck's avatar
rhenck committed
  highlightReceivingDropList: boolean = false;
  highlightReceivingDropListColor: string = '#006064';
  styling: BasicStyles & {
    itemBackgroundColor: string;
  };

rhenck's avatar
rhenck committed
  constructor(element?: DropListProperties) {
rhenck's avatar
rhenck committed
    if (element && isValid(element)) {
      this.value = element.value.map((value, index) => ({
        text: value.text,
        imgSrc: value.imgSrc,
        imgPosition: value.imgPosition,
        id: value.id,
        originListID: this.id,
        originListIndex: index,
        audioSrc: value.audioSrc
      }
      ));
      this.isSortList = element.isSortList;
rhenck's avatar
rhenck committed
      this.onlyOneItem = element.onlyOneItem;
      this.connectedTo = [...element.connectedTo];
      this.copyOnDrop = element.copyOnDrop;
      this.allowReplacement = element.allowReplacement;
      this.orientation = element.orientation;
      this.highlightReceivingDropList = element.highlightReceivingDropList;
      this.highlightReceivingDropListColor = element.highlightReceivingDropListColor;
      this.styling = { ...element.styling };
rhenck's avatar
rhenck committed
    } else {
      if (environment.strictInstantiation) {
        throw new InstantiationEror('Error at DropList instantiation', element);
      }
      this.value = element?.value !== undefined ?
        this.value = element.value.map((value, index) => ({
          text: value.text,
          imgSrc: value.imgSrc,
          imgPosition: value.imgPosition,
          id: value.id,
          originListID: this.id,
          originListIndex: index,
          audioSrc: value.audioSrc
        })) :
rhenck's avatar
rhenck committed
        [];
rhenck's avatar
rhenck committed
      if (element?.isSortList) this.isSortList = element.isSortList;
rhenck's avatar
rhenck committed
      if (element?.onlyOneItem) this.onlyOneItem = element.onlyOneItem;
      if (element?.connectedTo) this.connectedTo = [...element.connectedTo];
      if (element?.copyOnDrop) this.copyOnDrop = element.copyOnDrop;
      if (element?.allowReplacement) this.allowReplacement = element.allowReplacement;
      if (element?.orientation) this.orientation = element.orientation;
      if (element?.highlightReceivingDropList) this.highlightReceivingDropList = element.highlightReceivingDropList;
      if (element?.highlightReceivingDropListColor) {
        this.highlightReceivingDropListColor = element.highlightReceivingDropListColor;
      }
      this.dimensions = PropertyGroupGenerators.generateDimensionProps({
        height: 100,
        minHeight: 57,
rhenck's avatar
rhenck committed
        ...element?.dimensions
      });
      this.position = PropertyGroupGenerators.generatePositionProps(element?.position);
      this.styling = {
        ...PropertyGroupGenerators.generateBasicStyleProps({
          backgroundColor: '#ededed',
          ...element?.styling
        }),
        itemBackgroundColor: element?.styling?.itemBackgroundColor || '#c9e0e0'
      };
    }
  getDuplicate(): DropListElement {
    return new DropListElement(this);
  }

  /* Set originListID and originListIndex if applicable. */
  setProperty(property: string, value: UIElementValue): void {
    super.setProperty(property, value);
    if (property === 'value' || property === 'id') {
      this.value.forEach((dndValue: DragNDropValueObject, index) => { // foreach to keep the array ref intact
        this.value[index] = {
          ...dndValue,
          originListID: this.id,
          originListIndex: this.value.indexOf(dndValue)
  getVariableInfos(options: DropListElement[]): VariableInfo[] {
    return [{
      id: this.id,
      type: 'string',
      format: '',
      multiple: true,
      nullable: false,
      values: this.getVariableInfoValues(options),
      valuePositionLabels: [],
      page: '',
      valuesComplete: true
  private getVariableInfoValues(dropLists: DropListElement[]): VariableValue[] {
    const valueDropLists = dropLists.filter(dropList => dropList.connectedTo.includes(this.id));
    if (valueDropLists.length || this.isSortingList()) {
      return [this, ...valueDropLists]
        .map(dropList => dropList.value as DragNDropValueObject[])
        .flat()
        .map(option => ({ value: option.id, label: InputElement.stripHTML(option.text) }));
    return [];
  }

  private isSortingList(): boolean {
    return (!this.connectedTo.length && (this.value as DragNDropValueObject[]).length > 1);
  getElementComponent(): Type<ElementComponent> {
    return DropListComponent;
  }
}

export interface DropListProperties extends InputElementProperties {
  value: DragNDropValueObject[];
rhenck's avatar
rhenck committed
  isSortList: boolean;
  onlyOneItem: boolean;
  connectedTo: string[];
  copyOnDrop: boolean;
  allowReplacement: boolean;
  orientation: 'vertical' | 'horizontal' | 'flex';
  highlightReceivingDropList: boolean;
  highlightReceivingDropListColor: string;
  styling: BasicStyles & {
    itemBackgroundColor: string;
  };
}
rhenck's avatar
rhenck committed

function isValid(blueprint?: DropListProperties): boolean {
  if (!blueprint) return false;
  return blueprint.value !== undefined &&
rhenck's avatar
rhenck committed
    blueprint.isSortList !== undefined &&
rhenck's avatar
rhenck committed
    blueprint.onlyOneItem !== undefined &&
    blueprint.connectedTo !== undefined &&
    blueprint.copyOnDrop !== undefined &&
    blueprint.allowReplacement !== undefined &&
    blueprint.orientation !== undefined &&
    blueprint.highlightReceivingDropList !== undefined &&
    blueprint.highlightReceivingDropListColor !== undefined &&
    blueprint.styling !== undefined &&
    blueprint.styling.itemBackgroundColor !== undefined;
}