huridocs/uwazi

View on GitHub
app/react/utils/advancedSort.js

Summary

Maintainability
A
1 hr
Test Coverage
A
100%
const copyArray = array => array.concat();

const localCompare = (a, b) => a.toLowerCase().localeCompare(b.toLowerCase());

const compareDottedList = (a, b, options) => {
  const aParts = a.split('.');
  const bParts = b.split('.');

  const compareArray = options.listTypes.reduce((memo, type, index) => {
    if (aParts.length > index && bParts.length <= index) {
      memo.push(1);
      return memo;
    }

    if (aParts.length <= index && bParts.length > index) {
      memo.push(-1);
      return memo;
    }

    if (aParts.length > index && bParts.length > index) {
      const x = type(aParts[index]);
      const y = type(bParts[index]);
      if (x !== y) {
        memo.push(x < y ? -1 : 1);
        return memo;
      }
    }

    memo.push(0);
    return memo;
  }, []);

  return compareArray.reduce(
    (memo, indexCompare) => (!memo && indexCompare ? indexCompare : memo),
    0
  );
};

const compare = (baseA, baseB, options) => {
  const a = options.order === 'desc' ? baseB : baseA;
  const b = options.order === 'desc' ? baseA : baseB;

  if (options.treatAs === 'number') {
    return Number(a) - Number(b);
  }

  if (options.treatAs === 'dottedList') {
    return compareDottedList(a, b, options);
  }

  return localCompare(a, b);
};

const evalIfHasProperty = (data, property) =>
  typeof data === 'object' && data !== null && Object.keys(data).indexOf(property) !== -1;

const advancedSort = (array, options = {}) => {
  options.order = options.order || 'asc';
  const sortedArray = copyArray(array);

  if (options.property) {
    sortedArray.sort((baseA, baseB) => {
      let a;
      let b;

      if (!Array.isArray(options.property)) {
        a = baseA[options.property];
        b = baseB[options.property];
      }

      if (Array.isArray(options.property)) {
        a = options.property.reduce(
          (memo, property) => (evalIfHasProperty(memo, property) ? memo[property] : null),
          baseA
        );
        b = options.property.reduce(
          (memo, property) => (evalIfHasProperty(memo, property) ? memo[property] : null),
          baseB
        );
      }

      if (!a) {
        return 1;
      }
      if (!b) {
        return -1;
      }
      return compare(a, b, options);
    });
  }

  if (!options.property) {
    sortedArray.sort((a, b) => compare(a, b, options));
  }

  return sortedArray;
};

export { advancedSort };