huridocs/uwazi

View on GitHub
app/react/Library/components/SortButtons.tsx

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import React from 'react';
import { bindActionCreators, Dispatch } from 'redux';
import { connect, ConnectedProps } from 'react-redux';
import { actions } from 'react-redux-form';
import { wrapDispatch } from 'app/Multireducer';
import { Icon } from 'UI';
import { DropdownList } from 'app/Forms';
import { IImmutable } from 'shared/types/Immutable';
import { IStore } from 'app/istore';
import { omit } from 'lodash';
import {
  filterTemplates,
  getPropertySortType,
  getSortOptions,
  SearchOptions,
  SortType,
} from '../helpers/sortComponets';

interface SortButtonsOwnProps {
  stateProperty: string;
  selectedTemplates: IImmutable<string[]>;
  sortCallback: Function;
}

const mapStateToProps = (state: IStore, ownProps: SortButtonsOwnProps) => {
  let { templates } = state;
  const stateProperty = ownProps.stateProperty ? ownProps.stateProperty : 'library.search';

  if (ownProps.selectedTemplates && ownProps.selectedTemplates.count()) {
    templates = filterTemplates(state.templates, ownProps.selectedTemplates);
  }
  const search = stateProperty
    .split(/[.,/]/)
    .reduce(
      (memo: { [k: string]: any }, property: string) =>
        Object.keys(memo).indexOf(property) !== -1 ? memo[property] : null,
      state
    );
  return { ...ownProps, stateProperty, search, templates };
};

const mapDispatchToProps = (dispatch: Dispatch<{}>) =>
  bindActionCreators({ merge: actions.merge }, wrapDispatch(dispatch, 'library'));

const connector = connect(mapStateToProps, mapDispatchToProps);

type mappedProps = ConnectedProps<typeof connector>;

const getToggleSearchIcon = (search: SearchOptions) =>
  search.order === 'asc' && search.sort !== '_score' ? 'arrow-up' : 'arrow-down';

const validateSearch = (search: SearchOptions): SearchOptions =>
  search.sort === '_score' && !search.searchTerm
    ? {
        sort: 'creationDate',
        order: 'desc',
        searchTerm: search.searchTerm,
      }
    : { searchTerm: search.searchTerm, sort: search.sort };

const sortDirection = (condition: string) => {
  switch (condition) {
    case 'desc':
    case 'string':
      return 'asc';
    case 'asc':
    default:
      return 'desc';
  }
};

const SortButtonsComponent = ({
  search,
  merge,
  stateProperty,
  templates,
  sortCallback,
}: mappedProps) => {
  const doSort = (property: string, defaultTreatAs: string, selectedSort?: string) => {
    const treatAs = defaultTreatAs;
    const order = selectedSort || sortDirection(treatAs);
    const newSort = { sort: property, order, treatAs };
    merge(stateProperty, newSort);
    const filters = { ...search, ...omit(newSort, 'treatAs'), userSelectedSorting: true };
    return sortCallback && sortCallback({ search: filters }, 'library');
  };

  const changeOrder = () => {
    doSort(search.sort, search.treatAs, sortDirection(search.order));
  };

  const validatedSearch = validateSearch(search);

  const sortOptions = getSortOptions(search, templates);

  return (
    <div className="sort-buttons">
      <DropdownList
        className="sort-dropdown"
        value={validatedSearch.sort}
        data={sortOptions}
        valueField="value"
        textField="label"
        onChange={(selected: SortType) => doSort(selected.value, getPropertySortType(selected))}
      />
      <button
        type="button"
        disabled={search.sort === '_score'}
        className={`sorting-toggle ${search.sort === '_score' && 'disabled'}`}
        onClick={changeOrder}
      >
        <Icon icon={getToggleSearchIcon(search)} />
      </button>
    </div>
  );
};

const container = connector(SortButtonsComponent);
export type { SortButtonsOwnProps };
export { container as SortButtons, mapStateToProps };