hisptz/function-analytics

View on GitHub
src/model/analytics.js

Summary

Maintainability
C
1 day
Test Coverage
import { Fetcher } from '../utilities/fetcher';
import { AnalyticsResult } from '../result/analytics-result';
/**
 * @description
 * This represents the Analytics Fetcher for processing for making Web API calls
 * @example
 * const analytics = Fn.Analytics();
 * @extends Fetcher
 */
export class Analytics extends Fetcher {
  /**
   * @description
   * Creates an analytics fethcer
   *
   * @param {Number} version - The version of dhis analytics structure to use
   */
  constructor(version = 25) {
    super();
    if (typeof version === 'boolean') {
      if (version) {
        version = 25;
      } else {
        version = 26;
      }
    }
    this.parameters['dimension'] = {};
    this.postProcess(data => {
      return this.standardizeAnalytics(data, version);
    });
  }

  /**
   * Sets the data for the fetch
   * @param {string} dx The id of the data to get
   * @returns {Analytics} - Object with the analytics interaction properties
   */
  setData(dx) {
    this.setDimension('dx', dx);
    return this;
  }

  /**
   * Sets the period for the fetch
   * @param {string} pe The id of the period to get data from
   * @returns {Analytics} Object with the analytics interaction properties
   */
  setPeriod(pe) {
    this.setDimension('pe', pe);
    return this;
  }

  /**
   * Sets the organisation unit for the fetching of the analytics
   * @param {string} ou - Organisation unit
   * @returns {Analytics} Object with the analytics interaction properties
   */
  setOrgUnit(ou) {
    this.setDimension('ou', ou);
    return this;
  }

  /**
   * Sets the data,period and organisation unit from function input parameters object for the fetching of the analytics
   * @param {string} parameters - Rule parameters
   * @returns {Analytics} Object with the analytics interaction properties
   */
  setSelections(parameters) {
    this.setPeriod(parameters.pe);
    this.setOrgUnit(parameters.ou);
    // Set data Selection
    if (parameters.rule.json.data !== undefined) {
      // @TODO add support for only fetching 11char long uids, and joining them
      // into a comma separated string, so in future, parameters.rule.json.data
      // could simply be an indicator expresssion with unary operators and javascript
      // functions inside to be executed the express parameters.rule.json.data
      this.setData(parameters.rule.json.data);
    }
    // Set dynamic dimension
    if (parameters.dimensions !== undefined && Array.isArray(parameters.dimensions)) {
      parameters.dimensions.forEach(function (dimension) {
        if (Array.isArray(dimension.items)) {
          let dimensionItems = '';

          dimension.items.forEach(function (item) {
            dimensionItems.length > 0 ? dimensionItems += ';' + item : dimensionItems += item;
          });
          this.setDimension(dimension.id, dimensionItems);
        }
      });
    }
    return this;
  }

  /**
   * Sets the dimension for the fetching of the analytics
   * @param {string} dim - Dynamic Dimension identifier
   * @param {string} value - Dynamic dimension options identifiers
   * @returns {Analytics} Object with the analytics interaction properties
   */
  setDimension(dim, value) {
    this.parameters['dimension'][dim] = value ? value : '';
    return this;
  }

  /**
   * Standardizes the analytics object
   *
   * @param {Object} analyticsObject - The analytics object
   * @param {Number} version - The version of dhis analytics structure to use
   * @returns {AnalyticsResult} - Object with the analytics results
   */
  standardizeAnalytics(analyticsObject, version = 25) {
    if (typeof version === 'boolean') {
      if (version) {
        version = 25;
      } else {
        version = 26;
      }
    }
    // if Serverside Event clustering do nothing
    if (analyticsObject.count) {
      return analyticsObject;
    }
    let sanitizedAnalyticsObject = {
      headers: [],
      metaData: {
        dimensions: {},
        names: {},
        dx: [],
        pe: [],
        ou: [],
        co: []
      },
      rows: []
    };

    if (analyticsObject) {
      /**
       * Check headers
       */
      if (analyticsObject.headers) {
        analyticsObject.headers.forEach(header => {
          try {
            let newHeader = header;

            sanitizedAnalyticsObject.headers.push(newHeader);
          } catch (e) {
            console.warn('Invalid header object');
          }
        });
      }

      /**
       * Check metaData
       */
      if (analyticsObject.metaData) {
        try {
          let sanitizedMetadata = this.getSanitizedAnalyticsMetadata(
            analyticsObject.metaData,
            version
          );

          sanitizedAnalyticsObject.metaData = sanitizedMetadata;
        } catch (e) {
          console.warn('Invalid metadata object');
        }
      }

      /**
       * Check rows
       */
      if (analyticsObject.rows) {
        sanitizedAnalyticsObject.rows = analyticsObject.rows;
      }
    }
    sanitizedAnalyticsObject.height = analyticsObject.height;
    sanitizedAnalyticsObject.width = analyticsObject.width;
    return new AnalyticsResult(sanitizedAnalyticsObject);
  }

  /**
   * Standardizes the analytics metadata object
   *
   * @param {Object} analyticMetadata - The analytics metadata object
   * @param {Number} version - The version of dhis analytics structure to use
   * @returns {Object} - Object with the analytics metadata
   */
  getSanitizedAnalyticsMetadata(analyticMetadata, version) {
    let sanitizedMetadata = {};

    if (analyticMetadata) {
      if (analyticMetadata.ouHierarchy) {
        sanitizedMetadata.ouHierarchy = analyticMetadata.ouHierarchy;
      }
      if (version < 26) {
        // Get old structure
        sanitizedMetadata.names = {};
        if (analyticMetadata.names) {
          sanitizedMetadata.names = analyticMetadata.names;
        } else if (analyticMetadata.items) {
          Object.keys(analyticMetadata.items).forEach(nameKey => {
            sanitizedMetadata.names[nameKey] =
              analyticMetadata.items[nameKey].name;
          });
        }

        if (analyticMetadata.dimensions) {
          Object.keys(analyticMetadata.dimensions).forEach(nameKey => {
            sanitizedMetadata[nameKey] = analyticMetadata.dimensions[nameKey];
          });
        }
      } else {
        // Get new structure
        sanitizedMetadata.items = {};
        if (analyticMetadata.items) {
          sanitizedMetadata.items = analyticMetadata.items;
        } else if (analyticMetadata.names) {
          Object.keys(analyticMetadata.items).forEach(nameKey => {
            analyticMetadata.items[nameKey] = {
              name: analyticMetadata.names[nameKey]
            };
          });
        }

        if (!analyticMetadata.dimensions) {
          sanitizedMetadata.dimensions = {};
          Object.keys(analyticMetadata).forEach(nameKey => {
            if (['names', 'items', 'dimensions'].indexOf(nameKey) === -1) {
              sanitizedMetadata.dimensions[nameKey] = analyticMetadata[nameKey];
            }
          });
        } else {
          sanitizedMetadata.dimensions = analyticMetadata.dimensions;
        }
      }
    }
    return sanitizedMetadata;
  }

  /**
   * Gets the url for fetching
   * @returns {string}
   */
  get url() {
    return 'analytics?' + this._urlParameters;
  }
}