huridocs/uwazi

View on GitHub
app/react/Relationships/components/RelationshipMetadata.js

Summary

Maintainability
A
0 mins
Test Coverage
A
94%
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { actions as formActions } from 'react-redux-form';
import Immutable from 'immutable';
import { createSelector } from 'reselect';
import { Icon } from 'UI';
import { withContext } from 'app/componentWrappers';
import { ShowMetadata, MetadataForm, MetadataFormButtons, actions } from 'app/Metadata';
import { Translate, I18NLink } from 'app/I18N';
import SidePanel from 'app/Layout/SidePanel';
import { CopyFromEntity } from 'app/Metadata/components/CopyFromEntity';
import { api as entitiesAPI } from 'app/Entities';
import { RequestParams } from 'app/utils/RequestParams';
import { saveEntityWithFiles } from 'app/Library/actions/saveEntityWithFiles';
import { AttachmentsList } from 'app/Attachments';
import { FileList } from 'app/Attachments/components/FileList';
import {
  unselectConnection,
  updateRelationshipEntityData,
  addEntity,
  setAddToData,
  reloadRelationships,
} from '../actions/actions';

class RelationshipMetadata extends Component {
  constructor(props) {
    super(props);
    this.state = { copyFrom: false, copyFromProps: [] };

    this.toggleCopyFrom = this.toggleCopyFrom.bind(this);
    this.onCopyFromSelect = this.onCopyFromSelect.bind(this);
    this.deleteDocument = this.deleteDocument.bind(this);
    this.saveEntity = this.saveEntity.bind(this);
    this.closeSidePanel = this.closeSidePanel.bind(this);
  }

  onCopyFromSelect(copyFromProps) {
    this.setState({ copyFromProps });
  }

  async deleteDocument() {
    this.props.mainContext.confirm({
      accept: async () => {
        this.props.unselectConnection();
        await entitiesAPI.delete(new RequestParams({ sharedId: this.props.entity.sharedId }));
        await this.props.reloadRelationships(this.props.parentSharedId);
      },
      title: 'Confirm deletion of entity',
      message: 'Are you sure you want to delete this entity?',
    });
  }

  async saveEntity(entity, formModel) {
    this.props.resetForm(formModel);
    this.props.unselectConnection();
    const { entity: savedEntity, errors } = await saveEntityWithFiles(entity);
    this.props.updateRelationshipEntityData(savedEntity);

    if (Number.isInteger(this.props.hubIndex)) {
      this.props.addEntity(
        this.props.hubIndex,
        this.props.rightRelationshipIndex,
        savedEntity,
        errors
      );
      this.props.setAddToData(null, null);
    }
  }

  toggleCopyFrom() {
    this.setState(currentState => ({
      copyFrom: !currentState.copyFrom,
    }));
  }

  closeSidePanel() {
    return this.props.entityBeingEdited
      ? this.props.resetForm('relationships.metadata')
      : this.props.unselectConnection();
  }

  renderForm() {
    const form = (
      <MetadataForm
        model="relationships.metadata"
        initialTemplateId={this.props.entity.template}
        templateId={this.props.formMetadata.template}
        onSubmit={this.saveEntity}
        changeTemplate={this.props.changeTemplate}
        highlightedProps={this.state.copyFromProps}
      />
    );

    return this.state.copyFrom ? (
      <div className="tab-content tab-content-visible">
        {form}
        <CopyFromEntity
          isVisible={this.state.copyFrom}
          originalEntity={this.props.formMetadata}
          templates={this.props.templates}
          onSelect={this.onCopyFromSelect}
          formModel="relationships.metadata"
          onCancel={this.toggleCopyFrom}
        />
      </div>
    ) : (
      form
    );
  }

  renderBody() {
    return this.props.entityBeingEdited ? (
      this.renderForm()
    ) : (
      <>
        <ShowMetadata entity={this.props.entity} showTitle showType />
        <FileList entity={this.props.entity} files={this.props.entity.documents} readonly />
        <AttachmentsList
          entity={this.props.entity}
          attachments={this.props.entity.attachments}
          readOnly
        />
      </>
    );
  }

  renderButtons() {
    if (this.props.entityBeingEdited) {
      return (
        <MetadataFormButtons
          data={Immutable.fromJS(this.props.entity)}
          delete={this.deleteDocument}
          formStatePath="relationships.metadata"
          formState={this.props.formState}
          entityBeingEdited={this.props.entityBeingEdited}
          copyFrom={this.toggleCopyFrom}
          hideDelete={this.props.hubsBeingEdited}
          includeViewButton={false}
        />
      );
    }
    return (
      <I18NLink
        to={`entity/${this.props.entity.sharedId}`}
        className="btn btn-default"
        tabIndex="0"
      >
        <Icon icon="file" />
        <span className="btn-label">
          <Translate>View</Translate>
        </span>
      </I18NLink>
    );
  }

  render() {
    const twoColumns = this.state.copyFrom ? 'two-columns' : '';
    return (
      <SidePanel
        open={this.props.selectedConnection}
        className={`connections-metadata ${twoColumns}`}
      >
        {!this.state.copyFrom && (
          <button
            type="button"
            className="closeSidepanel close-modal"
            onClick={this.closeSidePanel}
          >
            <Icon icon="times" />
          </button>
        )}
        <div className="sidepanel-body">{this.renderBody()}</div>
        <div className="sidepanel-footer">{this.renderButtons()}</div>
      </SidePanel>
    );
  }
}

RelationshipMetadata.defaultProps = {
  selectedConnection: false,
  entityBeingEdited: false,
  hubsBeingEdited: false,
  hubIndex: null,
  rightRelationshipIndex: null,
};

RelationshipMetadata.propTypes = {
  selectedConnection: PropTypes.bool,
  entity: PropTypes.object.isRequired,
  formMetadata: PropTypes.object.isRequired,
  formState: PropTypes.object.isRequired,
  unselectConnection: PropTypes.func.isRequired,
  entityBeingEdited: PropTypes.bool,
  templates: PropTypes.instanceOf(Immutable.List).isRequired,
  updateRelationshipEntityData: PropTypes.func.isRequired,
  changeTemplate: PropTypes.func.isRequired,
  hubIndex: PropTypes.number,
  rightRelationshipIndex: PropTypes.number,
  addEntity: PropTypes.func.isRequired,
  setAddToData: PropTypes.func.isRequired,
  resetForm: PropTypes.func.isRequired,
  hubsBeingEdited: PropTypes.bool,
  parentSharedId: PropTypes.string.isRequired,
  reloadRelationships: PropTypes.func.isRequired,
  mainContext: PropTypes.shape({
    confirm: PropTypes.func,
  }).isRequired,
};

const connectionSelector = createSelector(
  state => state.relationships.connection,
  entity => (entity && entity.toJS ? entity.toJS() : { metadata: {} })
);

const mapStateToProps = state => {
  const entityBeingEdited = Boolean(state.relationships.metadata.metadata);

  return {
    selectedConnection: Boolean(
      (state.relationships.connection && state.relationships.connection.get('_id')) ||
        entityBeingEdited
    ),
    entity: connectionSelector(state),
    entityBeingEdited,
    hubsBeingEdited: Boolean(state.relationships.hubActions.get('editing')),
    templates: state.templates,
    formMetadata: state.relationships.metadata,
    formState: state.relationships.formState,
    hubIndex: state.relationships.hubActions.getIn(['addTo', 'hubIndex']),
    rightRelationshipIndex: state.relationships.hubActions.getIn([
      'addTo',
      'rightRelationshipIndex',
    ]),
    parentSharedId: state.relationships.list.sharedId,
  };
};

function mapDispatchToProps(dispatch) {
  return bindActionCreators(
    {
      unselectConnection,
      updateRelationshipEntityData,
      changeTemplate: actions.changeTemplate,
      addEntity,
      setAddToData,
      resetForm: formActions.reset,
      reloadRelationships,
    },
    dispatch
  );
}

export { RelationshipMetadata, mapStateToProps };

export default connect(mapStateToProps, mapDispatchToProps)(withContext(RelationshipMetadata));