Manual Reference Source Test

src/helpers/Section.js

import SectionModel from '../models/Section';
// import { serviceFactory } from '../utilities/factories/ServiceFactory';
import Helper from './Helper';
import { aggregate } from '../utilities/ClassUtility';
import FlowService from '../services/FlowService';
import StatusService from '../services/StatusService';
import { validate, hasToken, isRequired } from '../utilities/ValidationUtility';

/**
 * Helper class representing a Section.
 */
class Section extends aggregate(SectionModel, Helper) {
  /**
   * Constructor for Section
   *
   * @param  {!Object} response - Requires all fields that are necessary for SectionModel
   *
   * @return {Section}             Returns a new Section instance
   */
  constructor(response) {
    super(response);
    /** @type {String} */
    this.type = this.type || 'sections';
    /** @type {Object[]} */
    this._sections = [];
    // Map children to sections
    if (response.sub_statuses) {
      this.connectChildren(response.sub_statuses);
    }
  }

  /** @type {String}  - The type */
  static get type() {
    return 'sections';
  }

  /** @type {String}  - The type */
  get type() {
    return this._type || 'sections';
  }

  /** @type {String}  - The type */
  set type(t) {
    this._type = t;
  }

  /**
   * Get Sections
   *
   * @return {Array<Object>} - Array of objects depending on the type of sub sections.
   */
  get sections() {
    return this._sections;
  }

  /**
   * Get Status and set it to this.status
   *
   * @return {Promise} - A Promise containing the status (String)
   */
  getStatus() {
    validate('Section getStatus()',
      hasToken(),
      isRequired({
        type: this.type,
        object: this.object,
        ownerType: this.ownerType,
        owner: this.owner,
      }));

    return (new StatusService()).getStatus(
      this.type,
      this.object,
      this.ownerType,
      this.owner
    ).then(data => (this.status = data.status.value));
  }

  /**
   * Synchronize Sections if the content is a section this will load sections belonging to it
   *
   * @return {Promise} - A Promise of an array of objects depending on the type of sub sections.
   */
  getChildren() {
    validate('Section getChildren()',
      hasToken(),
      isRequired({
        owner: this.owner,
        ownerType: this.ownerType,
        name: this.object,
      }));
    const { object: name, owner, ownerType } = this;
    return (new StatusService()).getSections(name, ownerType, owner).then((d) => {
      /** @type {String} */
      this.status = d.section_status.value;

      // copy over the section status array to 'section' and create data Object() if necessary
      this.connectChildren(d.section_status.sub_statuses);
      return this._sections;
    });
  }

  /**
   * Gets the data depending on 'type' and the 'object' fields
   *
   * @return {Section}
   *
   * @memberOf Section
   */
  getData() {
    const section = this;
    const { owner, ownerType } = section;
    return new Promise((resolve, reject) => {
      switch (section.type) {
        case 'data_collection/flow_process':
          (new FlowService()).getFlow(section.object).then((f) => {
            section.data = f;
            section.data.status = section.value;
            section.data.options = { owner, ownerType };
            resolve(section);
          }).catch((reason) => {
            reject(reason);
          });
          break;
        case 'section':
          // TODO add StatusService
          // (new ContentService()).geContent(section.object).then(c => (section.data = c));
          (new StatusService()).getSections(section.object, ownerType, owner).then((c) => {
            section.data = c;
            section.data.status = section.value;
            section.data.label = section.label;
            section.data.object = section.object;
            resolve(section);
          }).catch((reason) => {
            reject(reason);
          });
          break;
        default: // section.data = undefined;
          resolve(null);
          break;
      }
    });
  }

  /**
   * Connects children and provides appropriate data elements in the data field.  It is important
   * to note that invalid children will only have Section wrappers but no data.  This will not
   * throw any errors when there is no data from the server.  Check the network capability of
   * the browser or developer tool (Charles etc) to find invalid calls.
   *
   * @param {Array<any>} childArray - should contain an array of deserialized Sections in JSON
   *
   * @memberOf Section
   */
  connectChildren(childArray) {
    const { owner, ownerType } = this;
    this._sections = childArray.map((obj) => {
      const section = new Section(Object.assign({}, { ownerType, owner }, obj));

      // Get section information but skip over invalid children
      section.getData().catch(() => {});

      return section;
    });
  }

  /**
   * Transition between states using actions
   *
   * @param  {String} action - The action must be a string like 'acknowledge'
   *
   * @return {Promise} Returns a promise but will alsoassign the new state to the Flow intance
   */
  transition(action) {
    return (new StatusService()).transition(
      action,
      this.type,
      this.object,
      this.ownerType,
      this.owner
    ).then(data => (this.status = data.status.value));
  }
}

export default Section;