Example #1
0
export const UploadGeneSet = withProps(({ CreateButton }) => ({
  CreateSetButton: withProps(() => ({
    CreateButton: CreateButton || CreateExploreGeneSetButton,
    idMap: geneMap,
    idKey: 'gene_id',
    mainField: 'genes.gene_id',
  }))(CreateSetButton),
  inputProps: {
    type: 'gene',
    placeholder: 'e.g. ENSG00000155657, TTN, 7273, HGNC:12403, 188840, Q8WZ42',
    helpText: (
      <div>
        <div style={{ maxWidth: '50rem', whiteSpace: 'initial' }}>
          - Gene identifier accepted:{' '}
          {Object.values(GENE_ID_FIELD_DISPLAY).join(', ')}
        </div>
        - Delimiters between gene identifiers: comma, space, tab or 1 gene
        identifier per line<br />
        <FileFormats />
      </div>
    ),
  },
  MappingTable: GeneMappingTable,
  validateHits: geneValidateHits,
  idMap: geneMap,
  heading: 'Upload Gene Set',
  validatingMessage: (
    <span>
      <SpinnerIcon /> validating genes
    </span>
  ),
}))(Base);
Example #2
0
export const UploadSsmSet = withProps(({ CreateButton }) => ({
  CreateSetButton: withProps(() => ({
    CreateButton: CreateButton || CreateExploreSsmSetButton,
    idMap: ssmMap,
    idKey: 'ssm_id',
    mainField: 'ssms.ssm_id',
  }))(CreateSetButton),
  inputProps: {
    displayType: 'mutation',
    placeholder:
      'e.g. chr3:g.179234297A>G, 92b75ae1-8d4d-52c2-8658-9c981eef0e57',
    helpText: (
      <div>
        <div style={{ maxWidth: '50rem', whiteSpace: 'initial' }}>
          - Mutation identifier accepted:{' '}
          {Object.values(SSM_ID_FIELD_DISPLAY).join(', ')}
        </div>
        - Delimiters between mutation identifiers: comma, space, tab or 1
        mutation identifier per line<br />
        <FileFormats />
      </div>
    ),
  },
  MappingTable: SsmMappingTable,
  validateHits: ssmValidateHits,
  idMap: ssmMap,
  heading: 'Upload Mutation Set',
  validatingMessage: (
    <span>
      <SpinnerIcon /> validating mutations
    </span>
  ),
}))(Base);
Example #3
0
export const UploadCaseSet = withProps(({ CreateButton }) => ({
  CreateSetButton: withProps(() => ({
    CreateButton: CreateButton || CreateRepositoryCaseSetButton,
    idMap: caseMap,
    idKey: 'case_id',
    mainField: 'cases.case_id',
  }))(CreateSetButton),
  inputProps: {
    type: 'case',
    placeholder:
      'e.g. TCGA-DD-AAVP, TCGA-DD-AAVP-10A-01D-A40U-10, 0004d251-3f70-4395-b175-c94c2f5b1b81',
    helpText: (
      <div>
        <div style={{ maxWidth: '50rem', whiteSpace: 'initial' }}>
          - Case identifier accepted:{' '}
          {Object.values(CASE_ID_FIELD_DISPLAY).join(', ')}
        </div>
        - Delimiters between case identifiers: comma, space, tab or 1 case
        identifier per line<br />
        <FileFormats />
      </div>
    ),
  },
  MappingTable: CaseMappingTable,
  validateHits: caseValidateHits,
  idMap: caseMap,
  heading: 'Upload Case Set',
  validatingMessage: (
    <span>
      <SpinnerIcon /> validating cases
    </span>
  ),
}))(Base);
export default function createSimpleDialog(props) {
  return compose(
    withDialog({
      isDraggable: true,
      width: 400,
      ...props.dialogProps
    }),
    reduxForm({
      form: props.formName
    }),
    withProps(props)
  )(SimpleGenericDialogForm);
}
Example #5
0
const withReduxForm = (initialState, mapProps = defaultMapProps) => {
  const hoc = compose(
    withProps((props) => ({
      ...props,
      ...mapProps(props)
    })),
    reduxForm(initialState)
  )
  if (process.env.NODE_ENV !== 'production') {
    return (BaseComponent) =>
      setDisplayName(wrapDisplayName(BaseComponent, 'withReduxForm'))(hoc(BaseComponent))
  }
  return hoc
}
  it('renames a single prop', () => {
    const spy = createSpy()
    const StringConcat = compose(
      withProps({ so: 123, la: 456 }),
      renameProp('so', 'do'),
      spy
    )('div')

    expect(StringConcat.displayName).to.equal(
      'withProps(renameProp(spy(div)))'
    )

    renderIntoDocument(<StringConcat />)

    expect(spy.getProps()).to.eql({ do: 123, la: 456 })
  })
Example #7
0
export default mapThemeToCss => {
  let refs = 0;
  let sheet = null;
  let cache = null;

  const attach = (nextState, force = false) => {
    if (isEqual(nextState, cache)) return;

    cache = nextState;
    if (force || !sheet) sheet = jss.createStyleSheet(nextState);
    sheet.attach();
  };

  const ref = (nextState) => {
    if (refs === 0) attach(nextState);
    refs++;
    return sheet;
  };

  const deref = () => {
    refs--;
    if (refs === 0) {
      sheet.detach();
      cache = null;
    }
  };

  return compose(
    lifecycle({
      componentWillMount() {
        const nextState = mapThemeToCss(this.props.theme);
        ref(nextState);
      },
      componentWillReceiveProps(nextProps) {
        if (!isEqual(this.props.theme, nextProps.theme)) {
          attach(mapThemeToCss(nextProps.theme), true);
        }
      },
      componentWillUnmount() {
        deref();
      }
    }),
    withProps(() => ({
      sheet
    }))
  );
};
  // sets a fetching flag on the state tree.
  actions.request()
  // dispatch a promise to be unpacked by redux-promise to send the result to
  // the reducer to update the state tree with the route times
  actions.routeTimeFetch(axios.get(`/fetch/times/${routeNumber}/${direction}/${stopID}`))
    .then(function fulfilled () {
      actions.requestSuccess()
    })
}

// Looking at the source code for lifecycle it does not look like this is
// optional....
function teardown () {
  return null
}

const goHome = curry(function goHome (push, event) {
  event.preventDefault()
  return push('/')
})

// wrapping the component in a Higher Order Component (HCO)
export default compose(
  pure,
  withProps({ goHome }),
  lifecycle(
    setup,
    teardown
  ),
)(RouteTimesWrapper)
import React from 'react';
import { compose, withProps } from 'recompose';
import { connect } from 'react-redux';
import { get } from 'lodash';

import { removeFilesFromCart, addAllFilesInCart } from '@ncigdc/dux/cart';
import Button from '@ncigdc/uikit/Button';
import ShoppingCartIcon from '@ncigdc/theme/icons/ShoppingCart';
import { SpinnerIcon } from '../../theme/icons/index';

export default compose(
  connect(state => ({ cartFiles: state.cart.files })),
  withProps(props => {
    return {
      files: get(props, 'filesViewer.repository.files.hits.edges', []).map(
        x => x.node,
      ),
    };
  }),
)(({ dispatch, cartFiles, style, loading, files, ...props }) => {
  const hasFilesToAdd = files.filter(
    f => !cartFiles.some(cf => cf.file_id === f.file_id),
  ).length;
  const cartOperation = hasFilesToAdd ? addAllFilesInCart : removeFilesFromCart;

  return (
    <Button
      style={style}
      className="test-cart-file-toggle"
      onClick={() => !loading && dispatch(cartOperation(files))}
      leftIcon={loading ? <SpinnerIcon /> : <ShoppingCartIcon />}
      (eA: string)
    }
    {
      // $ExpectError hello nor any nor number
      (hello: number)
    }
  </div>;

const enhacer: HOC<*, EnhancedCompProps> = compose(
  withPropsOnChange(["eA"], ({ eA }) => ({
    hello: `${eA}`
  })),
  withProps(props => ({
    hello: (props.hello: string),
    eA: (props.eA: number),
    // $ExpectError hello nor any nor number
    helloErr: (props.hello: number),
    // $ExpectError eA nor any nor string
    eAErr: (props.eA: string)
  })),
  withProps(props => ({
    // $ExpectError property not found
    err: props.iMNotExists
  }))
);

const enhacerFn: HOC<*, EnhancedCompProps> = compose(
  withPropsOnChange(
    (props, nextProps) => {
      (props.eA: number);
      (nextProps.eA: number);
      // $ExpectError eA nor any nor string
import { Map } from 'immutable';
import { compose, withProps, setPropTypes } from 'recompose';
import { withModels } from 'ui/utils/hocs';
import SiteUserOrgItem from 'ui/containers/SiteUsers/SiteUserOrgItem';

const enhance = compose(
  setPropTypes({
    user: PropTypes.instanceOf(Map).isRequired
  }),
  withProps(({ user }) => {
    const schema = 'organisation';
    const organisations = user
      .get('organisations')
      .map(org => new Map({ $oid: org }));
    const filter = new Map({
      _id: new Map({
        $in: organisations
      })
    });

    return { schema, filter };
  }),
  withModels
);

const render = ({ models, user }) => {
  const orgsItems = models
    .map(org => <SiteUserOrgItem org={org} user={user} />)
    .valueSeq();
  return <ul>{orgsItems}</ul>;
};
Example #12
0
import { unsubscribe } from '/imports/api/discussions/methods';

import renderUnsubscribePage from '../helpers/withState';

const enhancer = compose(
  lifecycle({
    componentDidMount() {
      const { documentId, documentType } = this.props;

      unsubscribe.call({ documentId, documentType }, handleMethodResult((error) =>
        this.props.setState({ error, loading: false })
      ));
    },
  }),
  withProps({
    children: (
      <h3>You've successfully unsubscribed from this discussion's notifications</h3>
    ),
  }),
);

const Notifications = renderUnsubscribePage(enhancer);


Notifications.propTypes = {
  documentId: PropTypes.string.isRequired,
  documentType: PropTypes.string.isRequired,
};

export default Notifications;
Example #13
0
  );
};

TextAreaArgInput.propTypes = {
  updateValue: PropTypes.func.isRequired,
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
  confirm: PropTypes.string,
  commit: PropTypes.func.isRequired,
  renderError: PropTypes.func,
  argId: PropTypes.string.isRequired,
};

const EnhancedTextAreaArgInput = compose(
  withProps(({ onValueChange, typeInstance, argValue }) => ({
    confirm: get(typeInstance, 'options.confirm'),
    commit: onValueChange,
    value: argValue,
  })),
  createStatefulPropHoc('value')
)(TextAreaArgInput);

EnhancedTextAreaArgInput.propTypes = {
  argValue: PropTypes.any.isRequired,
  onValueChange: PropTypes.func.isRequired,
  typeInstance: PropTypes.object.isRequired,
  renderError: PropTypes.func.isRequired,
};

export const textarea = () => ({
  name: 'textarea',
  displayName: 'Textarea',
Example #14
0
type EnhancedCompProps = { eA: 1 }

const Comp = ({ eA }) =>
  <div>
    {(eA: number)}
    {
      // $ExpectError eA nor any nor string
      (eA: string)
    }
  </div>

const enhacer: HOC<*, EnhancedCompProps> = compose(
  withContext({}, props => {
    // $ExpectError eA nor any nor string
    ;(props.eA: string)
    return {}
  }),
  withProps(props => ({
    eA: (props.eA: number),
    // $ExpectError eA nor any nor string
    eAErr: (props.eA: string),
  })),
  withProps(props => ({
    // $ExpectError property not found
    err: props.iMNotExists,
  }))
)

const EnhancedComponent = enhacer(Comp)
Example #15
0
      await loadBrowserRegistries(types, basePath);

      // set app state to ready
      dispatch(appReady());
    } catch (e) {
      dispatch(appError(e));
    }
  },
  setAppError: payload => dispatch(appError(payload)),
});

const mergeProps = (stateProps, dispatchProps, ownProps) => {
  return {
    ...ownProps,
    ...stateProps,
    ...dispatchProps,
    setAppReady: dispatchProps.setAppReady(stateProps.basePath),
  };
};

export const App = compose(
  connect(
    mapStateToProps,
    mapDispatchToProps,
    mergeProps
  ),
  withProps(() => ({
    onRouteChange: trackRouteChange,
  }))
)(Component);
export default (schemaDefinition) => {
  const schema = new SimpleSchema(schemaDefinition);
  return withProps({
    schema,
  });
};
import React, { PropTypes } from 'react';
import { compose, withProps, setPropTypes } from 'recompose';
import ConfirmModal from 'ui/components/Modal/ConfirmModal';

const enhanceConfirmModal = compose(
  setPropTypes({
    target: PropTypes.string.isRequired,
  }),
  withProps(({ target }) => ({
    title: 'Confirm delete',
    message: (
      <span>
        This will delete the {target} <b>permanently</b>. Are you sure?
      </span>
    )
  })),
);

export default enhanceConfirmModal(ConfirmModal);

const getTypeFromMime = (mime) => {
  const match = TYPES.find(([matcher]) => matcher.test(mime));
  if (!match) { return null; }
  return match[1];
};

const mapDispatchToProps = dispatch => ({
  importAsset: bindActionCreators(assetActions.importAsset, dispatch),
});

const autoFileDrop = compose(
  withProps(({ type }) => {
    if (!type) { return null; }

    const accepts = ACCEPTS[type];

    return { accepts };
  }),
  connect(null, mapDispatchToProps),
  withHandlers({
    onDrop: ({ importAsset, onDrop }) =>
      (acceptedFiles) => {
        acceptedFiles.forEach((file) => {
          const type = getTypeFromMime(file.type);

          importAsset(file, type)
            .then(({ id }) => {
              onDrop(id);
            });
        });
      {!disabled &&
        <div className="form-group">
          <button
            className="btn btn-primary pull-right"
            onClick={handleImportPersonas}>
            Import Personas
            </button>
        </div>
      }
    </div>
  );
};

export default compose(
  withProps(({ model }) => ({
    schema,
    id: model.get('_id')
  })),
  withModel,
  connect(
    (state, { schema: connectSchema, id }) => ({
      model: modelsSchemaIdSelector(connectSchema, id, { deep: true })(state)
    }),
    { importPersonas }
  ),
  disabledState,
  handlers
)(
  ConfigureUploadComponent
  );
Example #20
0
    const { data } = template || { data: undefined };
    const { heading: templateHeading } = data || { heading: undefined };
    if (templateHeading) {
      this.heading = templateHeading;
    } else {
      this.heading = {
        defaultValue: "Address Book",
        i18nKey: "accountsUI.addressBook"
      };
    }
  }

  onData(null, {
    addressBook,
    countries,
    heading: this.heading,
    initMode,
    regionsByCountry
  });
}

registerComponent("AddressBook", AddressBook, [
  composeWithTracker(composer),
  withProps(handlers)
]);

export default compose(
  composeWithTracker(composer),
  withProps(handlers)
)(AddressBook);
import {compose, withProps, withPropsOnChange, withState} from 'recompose';
import {withDefaultProps} from './';
import {sanitizeDate, withImmutableProps} from '../utils';
import enhanceHeader from '../Header/withMultipleDates';
import format from 'date-fns/format';
import parse from 'date-fns/parse';

// Enhance Day component to display selected state based on an array of selected dates
export const enhanceDay = withPropsOnChange(['selected'], props => ({
  isSelected: props.selected.indexOf(props.date) !== -1,
}));

// Enhance year component
const enhanceYears = withProps(({displayDate}) => ({
  selected: displayDate ? parse(displayDate) : null,
}));

// Enhancer to handle selecting and displaying multiple dates
export const withMultipleDates = compose(
  withDefaultProps,
  withState('scrollDate', 'setScrollDate', getInitialDate),
  withState('displayDate', 'setDisplayDate', getInitialDate),
  withImmutableProps(({
    DayComponent,
    HeaderComponent,
    YearsComponent,
  }) => ({
    DayComponent: enhanceDay(DayComponent),
    HeaderComponent: enhanceHeader(HeaderComponent),
    YearsComponent: enhanceYears(YearsComponent),
  })),
Example #22
0
export const withSearch = passedInState => {
  // prefix props to avoid collisions with existing props for component being enhanced
  const defaultState = {
    results: [],
    query: '',
    isLoading: false,
    isInSearchMode: false,
    fileHistoryResult: [],
  };

  // prevent results that come back out-of-order from being displayed
  let timeOfMostRecentRequest = 0;

  return compose(
    withState('state', 'setState', _.defaults(passedInState, defaultState)),
    withRouter,
    withProps(({ setState }) => ({
      handleResults: async (results, timeOfRequest, query) => {
        if (timeOfMostRecentRequest === timeOfRequest) {
          if (query && !results.length && isUUID(query)) {
            const history = await fetchFileHistory(query);
            if (history && history.length) {
              return setState(s => ({
                ...s,
                fileHistoryResult: history,
                results: [],
                isLoading: false,
              }));
            }
          }
          setState(s => ({
            ...s,
            results,
            fileHistoryResult: [],
            isLoading: false,
          }));
        }
      },
    })),
    withHandlers({
      setQuery: ({ setState }) => q => {
        setState(s => ({ ...s, query: q.trim() }));
      },
      reset: ({ setState }) => () => {
        setState(s => ({
          ...s,
          query: '',
          isInSearchMode: false,
          isLoading: false,
        }));
      },
      fetchResults: ({ handleResults }) => (query, timeOfRequest) => {
        return throttledInvoker(() =>
          fetchApi(
            `/quick_search?query=${window.encodeURIComponent(query)}&size=5`,
            {
              headers: {
                'Content-Type': 'application/json',
              },
            },
          ).then(response => {
            let hits = [];
            if (response && response.data) {
              hits = response.data.query.hits;
            }
            return handleResults(hits, timeOfRequest, query);
          }),
        );
      },
    }),
    withHandlers({
      selectItem: ({ push, reset }) => (item: ISearchHit) => {
        push(extractFilePath(item));
        setTimeout(reset, 100);
      },
    }),
    withPropsOnChange(
      (props, nextProps) => props.state.query !== nextProps.state.query,
      ({
        state: { query, results, fileHistoryResult },
        setState,
        fetchResults,
      }) => {
        timeOfMostRecentRequest = new Date().getTime();
        if (query) {
          setState(s => ({ ...s, isLoading: true }));
          fetchResults(query, timeOfMostRecentRequest);
        } else if (
          (results && results.length) ||
          (fileHistoryResult && fileHistoryResult.length)
        ) {
          setState(s => ({ ...s, results: [], fileHistoryResult: [] }));
        } else {
          setState(s => ({ ...s, isLoading: false }));
        }
      },
    ),
  );
};
Example #23
0
export const UploadCaseSet = withProps(({ CreateButton }) => ({
  CreateSetButton: withProps(() => ({
    CreateButton: CreateButton || CreateRepositoryCaseSetButton,
    idMap: caseMap,
    idKey: 'case_id',
    mainField: 'cases.case_id',
  }))(CreateSetButton),
  inputProps: {
    type: 'case',
    placeholder:
      'e.g. TCGA-DD-AAVP, TCGA-DD-AAVP-10A-01D-A40U-10, 0004d251-3f70-4395-b175-c94c2f5b1b81',
    helpText: (
      <div>
        <div style={{ maxWidth: '50rem', whiteSpace: 'initial' }}>
          - Case identifier accepted:{' '}
          {Object.values(CASE_ID_FIELD_DISPLAY).join(', ')}
        </div>
        - Delimiters between case identifiers: comma, space, tab or 1 case
        identifier per line<br />
        <FileFormats />
      </div>
    ),
  },
  MappingTable: CaseMappingTable,
  validateHits: caseValidateHits,
  idMap: caseMap,
  heading: 'Upload Case Set',
  validatingMessage: (
    <span>
      <SpinnerIcon /> validating cases
    </span>
  ),
}))(Base);
Example #24
0
          onClick={addShareable}>
          New shareable link
        </button>
      </div>
      <ModelList
        schema="dashboardSharing"
        isLoading={false}
        hasMore={false}
        models={model.get('shareable', new List())}
        fetchMore={() => {}}
        ModelForm={ModelForm}
        ModelListItem={ModelListItemWithoutModel}
        parentModel={model}
        updateModel={updateModel}
        buttons={[(openLinkButton({ parentModel: model })), (deleteButton({ parentModel: model }))]}
        getDescription={mod => mod.get('title')}
        noItemsDisplay="No shared links - click 'New shareable link' to share your dashboard" />
      <hr />
    </div>
  );

export default compose(
  withProps(({ id }) => ({
    id,
    schema
  })),
  withModel,
  withStyles(styles),
  dashboardSharingHandlers
)(DashboardSharingComponent);
Example #25
0
import { withProps, compose } from 'recompose';
import {
  queryStringToQuery,
  modelQueryStringSelector
} from 'ui/redux/modules/search';
import { withModels, withModel } from 'ui/utils/hocs';
import { addModel } from 'ui/redux/modules/models';
import { routeNodeSelector } from 'redux-router5';
import ModelList from 'ui/containers/ModelList';
import SearchBox from 'ui/containers/SearchBox';
import PersonaView from './PersonaView';

const schema = 'persona';
const PersonaList = compose(
  withProps({
    schema,
    sort: fromJS({ _id: -1 })
  }),
  withModels,
  withModel
)(ModelList);

class PersonaManage extends Component {
  static propTypes = {
    addModel: PropTypes.func,
    personaId: PropTypes.string // optional
  };

  constructor(props) {
    super(props);
    this.state = {
      openModal: null,
Example #26
0
    shouldComponentUpdate(nextProps) {
      return this.props._id === nextProps.at ||
             (this.props.at === this.props._id && !nextProps.at) ||
             (this.props.at === this.props._id && nextProps.at !== this.props._id) ||
             !this.props.isMergedWithPreviousMessage && nextProps.isMergedWithPreviousMessage;
    },
    componentDidMount() {
      if (this.props.isSelected) {
        invoke(this.props, 'scrollToSelectedMessage', this);
      }
    },
  }),
  withHandlers({
    onMessageAvatarClick: openUserDetails,
    onMessageContentsClick: deselect,
    onMessageTimeClick: select,
    onMessageDelete: remove,
  }),
  withProps(transsoc({
    isAuthor,
    userAvatar: withUser(getAvatar),
    userFirstName: withUser(getFirstName),
    userFullNameOrEmail: withUser(getFullNameOrEmail),
    pathToMessage: getMessagePath,
    time: getMessageTime,
    contents: getMessageContents,
    pathToMessageToCopy: getPathToMessageToCopy,
    className: getClassName,
  }))
)(Message);
Example #27
0
  cursor: pointer;
  padding-left: 2px;
  &:hover {
    color: #0275d8
  }
  & > div {
    margin-right: 8px;
  }
`;

const enhance = compose(
  withStateToggle(false, 'isOpen', 'togglePopover'),
  withProps(({ fill, id }) => ({
    iconProps: {
      size: Timeline.LIST_ICON_SIZE,
      inline: true,
      id: `item-${id}`,
      fill,
    },
  })),
);

const TimelineListItem = ({
  label,
  date,
  userName,
  symbol,
  isOpen,
  iconProps,
  togglePopover,
  renderPopover,
}) => (
Example #28
0
import { compose, mapProps, withProps } from "recompose";

import type { HOC } from "recompose";

type EnhancedCompProps = { eA: 1 };

const Comp = ({ a }) =>
  <div>
    {(a: string)}
    {
      // $ExpectError
      (a: number)
    }
  </div>;

const enhacer: HOC<*, EnhancedCompProps> = compose(
  mapProps(p => ({
    a: "1"
  })),
  // If you need to to detect erros after a mapProps HOC
  // you need to explicitly set Types for all HOCs below
  // seems like this https://github.com/facebook/flow/issues/4342 issue
  withProps(props => ({
    a: (props.a: string),
    // $ExpectError but not
    e: Math.round(props.a)
  }))
);

enhacer(Comp);
Example #29
0
File: index.js Project: sives/Plio
import PropTypes from 'prop-types';
import React from 'react';
import { compose, withProps } from 'recompose';

import Form from '/imports/ui/react/forms/components/Form';
import ReviewAnnualDate from '../AnnualDate';
import { getFormProps } from '../helpers';

const enhance = compose(withProps(props => getFormProps(props)));

const ReviewAnnualDateForm = enhance(props => (
  <Form
    autosave
    initialFormData={props.initialFormData}
    onFormChange={props.onAnnualDateChanged}
  >
    <ReviewAnnualDate
      fieldName={props.fieldNames.annualDate}
    />
  </Form>
));

ReviewAnnualDateForm.propTypes = {
  data: PropTypes.object,
  documentKey: PropTypes.string,
  onAnnualDateChanged: PropTypes.func,
};

export default ReviewAnnualDateForm;
Example #30
0
import { connect } from 'react-redux';

import MessagesList from '../../components/MessagesList';
import { compose, withProps } from 'recompose';
import { transformMessages } from './helpers.js';
import { transsoc, pickFromDiscussion } from '/imports/api/helpers.js';

export default compose(
  connect(pickFromDiscussion(['at'])),
  withProps(transsoc({
    messages: transformMessages,
  }))
)(MessagesList);