Skip to content
Snippets Groups Projects
section.ts 4.08 KiB
Newer Older
  CompoundElement,
  PositionedUIElement,
  UIElement,
  UIElementValue,
  PlayerElement,
  InputElement, Measurement
} from 'common/models/elements/element';
rhenck's avatar
rhenck committed
import { TextElement } from 'common/models/elements/text/text';
import { ImageElement } from 'common/models/elements/media-elements/image';
import { ElementFactory } from 'common/util/element.factory';
import { AnswerScheme } from 'common/models/elements/answer-scheme-interfaces';
import { VisibilityRule } from 'common/models/visibility-rule';

export class Section {
rhenck's avatar
rhenck committed
  [index: string]: unknown;
  elements: PositionedUIElement[] = [];
  height: number = 400;
  backgroundColor: string = '#ffffff';
  dynamicPositioning: boolean = true;
  autoColumnSize: boolean = true;
  autoRowSize: boolean = true;
  gridColumnSizes: { value: number; unit: string }[] = [{ value: 1, unit: 'fr' }, { value: 1, unit: 'fr' }];
  gridRowSizes: { value: number; unit: string }[] = [{ value: 1, unit: 'fr' }];
  visibilityRules: VisibilityRule[] = [];
  constructor(blueprint?: Record<string, any>) {
    const sanitizedBlueprint = Section.sanitizeBlueprint(blueprint);
    if (sanitizedBlueprint.height) this.height = sanitizedBlueprint.height;
    if (sanitizedBlueprint.backgroundColor) this.backgroundColor = sanitizedBlueprint.backgroundColor;
    if (sanitizedBlueprint.dynamicPositioning !== undefined) this.dynamicPositioning = sanitizedBlueprint.dynamicPositioning;
    if (sanitizedBlueprint.autoColumnSize !== undefined) this.autoColumnSize = sanitizedBlueprint.autoColumnSize;
    if (sanitizedBlueprint.autoRowSize !== undefined) this.autoRowSize = sanitizedBlueprint.autoRowSize;
    if (sanitizedBlueprint.gridColumnSizes !== undefined) this.gridColumnSizes = sanitizedBlueprint.gridColumnSizes;
    if (sanitizedBlueprint.gridRowSizes !== undefined) this.gridRowSizes = sanitizedBlueprint.gridRowSizes;
    if (sanitizedBlueprint.visibilityDelay) this.visibilityDelay = sanitizedBlueprint.visibilityDelay;
    if (sanitizedBlueprint.visibilityRules) {
      this.visibilityRules = sanitizedBlueprint.visibilityRules
        .map(rule => new VisibilityRule(rule.id, rule.operator, rule.value));
    }
    this.elements =
      sanitizedBlueprint.elements?.map(element => ElementFactory.createElement({
rhenck's avatar
rhenck committed
        ...element,
        position: UIElement.initPositionProps(element.position)
      }) as PositionedUIElement) ||
      [];
rhenck's avatar
rhenck committed
  setProperty(property: string, value: UIElementValue): void {
    this[property] = value;
  }
rhenck's avatar
rhenck committed
  addElement(element: PositionedUIElement): void {
    element.position.dynamicPositioning = this.dynamicPositioning;
rhenck's avatar
rhenck committed
    this.elements.push(element);
  }

  /* Includes children of children, i.e. compound children. */
  getAllElements(elementType?: string): UIElement[] {
    let allElements: UIElement[] =
      this.elements.map(element => [element, ...(element as CompoundElement).getChildElements() || []])
        .flat();
    if (elementType) {
      allElements = allElements.filter(element => element.type === elementType);
    }
    return allElements;
  getAnswerScheme(dropLists: UIElement[]): AnswerScheme[] {
    return this.getAllElements()
      .filter(element => element.hasAnswerScheme())
rhenck's avatar
rhenck committed
      .map(element => ((element.type === 'drop-list') ?
        (element as InputElement).getAnswerScheme(dropLists) :
        (element as InputElement | PlayerElement | TextElement | ImageElement).getAnswerScheme()));

  static sanitizeBlueprint(blueprint?: Record<string, UIElementValue>): Partial<Section> {
    if (!blueprint) return {};

    return {
      ...blueprint,
      gridColumnSizes: typeof blueprint.gridColumnSizes === 'string' ?
        (blueprint.gridColumnSizes as string)
          .split(' ')
          .map(size => ({ value: Number(size.slice(0, -2)), unit: size.slice(-2) })) :
        blueprint.gridColumnSizes as Measurement[],
      gridRowSizes: typeof blueprint.gridRowSizes === 'string' ?
        (blueprint.gridRowSizes as string)
          .split(' ')
          .map(size => ({ value: Number(size.slice(0, -2)), unit: size.slice(-2) })) :
        blueprint.gridRowSizes as Measurement[]
    };
  }