Source: components/userComponents/monitoredArea/Annotation/zones/ZoneEditor.js

import React from 'react';
import ZoneCanvas from './ZoneCanvas';
import { API } from '../../../../../LocalConfiguration';
import ZonesMap from '../../../maps/ZonesMap';
import { deleteZone, updateZone } from '../../../../restmodules/ZoneRestModule';
import { withNamespaces } from 'react-i18next';
import { Tab, Tabs } from 'react-bootstrap';

/**
 * Container for zone annotating forms
 * @extends Component
 * @hideconstructor
 */
class ZoneEditor extends React.Component {
  /**
   * @constructs
   * @param props
   */
  constructor(props) {
    super(props);
    this.state = {
      isValid: {
        name: false,
        cameraVertices: false,
        worldVertices: false
      },
      submitEnabled: false,
      name: "",
      worldVertices: { "points": [] },
      cameraVertices: []
    };
  }

  /**
   *
   * @param id
   */
  handleDelete(id) {
    deleteZone(this.props.monitoredAreaID, id).then(this.props.closeScreen);
  }

  /**
   *
   * @param cameraVertices
   */
  onActualZoneChange = (cameraVertices) => {
    let isValid = this.state.isValid;
    if (cameraVertices.length > 0 && cameraVertices.length === this.state.worldVertices.points.length) {
      isValid.cameraVertices = true;
      isValid.worldVertices = true;
      this.setState({
        cameraVertices: cameraVertices,
        isValid: isValid
      });
    } else {
      isValid.cameraVertices = false;
      this.setState({
        cameraVertices: cameraVertices,
        isValid: isValid
      });
    }
  };
  /**
   *
   * @param worldVertices
   */
  onNewZoneMapChange = (worldVertices) => {
    let isValid = this.state.isValid;
    if (worldVertices.points.length > 0 && worldVertices.points.length === this.state.cameraVertices.length) {
      isValid.worldVertices = true;
      isValid.cameraVertices = true;
      this.setState({
        worldVertices: worldVertices,
        isValid: isValid
      });
    } else {
      isValid.worldVertices = false;
      this.setState({
        worldVertices: worldVertices,
        isValid: isValid
      });
    }
  };
  /**
   *
   * @param event
   */
  onNameChange = (event) => {
    const newName = event.target.value;
    let isValid = this.state.isValid;
    isValid.name = newName && newName.length > 0;
    this.setState({
      isValid: isValid,
      name: newName
    });
  };

  /**
   *
   * @param prevProps
   * @param prevState
   * @param snapshot
   */
  componentDidUpdate(prevProps, prevState, snapshot) {
    if (prevProps.nameOfZone !== this.props.nameOfZone) {
      let isValid = this.state.isValid;
      isValid.name = this.props.nameOfZone && this.props.nameOfZone.length > 0;
      this.setState({
        name: this.props.nameOfZone,
        isValid: isValid
      })
    }
  }

  /**
   *
   * @param key
   */
  switchAndSaveTab(key) {
    this.setState({
      tabKey: key
    });
  }

  /**
   *
   * @returns {*}
   */
  render() {
    const { t } = this.props;
    let submitEnabled = true;

    for (let key in this.state.isValid) {
      if (this.state.isValid.hasOwnProperty(key) && !this.state.isValid[key]) {
        submitEnabled = false;
        break;
      }
    }

    return (
      <div>

        {this.renderConfirmDeleteModal(t('forms.deleteZone') + "?")}

        <div className="box-body">
          <div className={(!this.state.isValid.name) ? "form-group has-error" : "form-group"}>
            <label>{t('forms.zoneName')}</label>
            <label className="control-label fa fa-info-circle info-icon"
                   data-toggle="tooltip"
                   title={t('forms.tooltip.zoneName')}/>
            <input
              type="text"
              className="form-control"
              placeholder={t('forms.name')}
              name="name"
              value={this.state.name}
              onChange={(event) => this.onNameChange(event)}
            />
            {this.state.isValid.name ? null :
              <span className="help-block">{t('forms.help.zoneName')}</span>}
          </div>

          <Tabs
            activeKey={this.state.tabKey}
            onSelect={key => this.switchAndSaveTab(key)}
            mountOnEnter={true}
            unmountOnExit={true}
          >
            <Tab eventKey="1" title={t('annotate.showMap')}>
              <ZonesMap
                onNewZoneMapChange={(data) => this.onNewZoneMapChange(data)}
                interactive={true}
                zones={this.props.zones}
                showZoneNames={false}
                monitoredAreaID={this.props.monitoredAreaID}
              />
            </Tab>
            <Tab eventKey="2" title={t('annotate.showCameraView')}>
              <ZoneCanvas
                loadUrl={API + "/screenshot/" + this.props.monitoredAreaID}
                refreshUrl={API + "/screenshot/" + this.props.monitoredAreaID + "?refresh=true"}
                onActualZoneChange={(data) => this.onActualZoneChange(data)}
                zones={this.props.zones}
              />
            </Tab>
          </Tabs>

          <div className="box-footer no-border">
            <div className="row form-group has-error">
              {this.state.isValid.worldVertices && this.state.isValid.cameraVertices ? null :
                <span className="help-block pull-right">{t('forms.help.annotate')}</span>}
            </div>
            <div className="row">
              {
                (this.props.zoneId !== undefined) ?
                  <div className="pull-left">
                    <a
                      className="btn-link-red"
                      data-toggle="modal"
                      data-target="#confirmDeleteModal"
                    >{t('forms.deleteZone')}</a>
                  </div>
                  : null
              }

              <div className="pull-right">
                <button className="btn btn-outline-primary"
                        onClick={this.props.closeScreen}
                >{t('forms.cancel')}</button>

                <button
                  type="submit"
                  className="btn btn-primary"
                  onClick={() => this.props.onEditorSubmit(this.state.name,
                    this.state.cameraVertices,
                    this.state.worldVertices)}
                  disabled={!submitEnabled}
                >
                  {this.props.submitLabel}
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    )
  }

  /**
   *
   * @param text
   * @returns {*}
   */
  renderConfirmDeleteModal(text) {
    const { t } = this.props;
    return (
      <div className="modal fade"
           id="confirmDeleteModal"
           tabIndex="-1"
           role="dialog"
           aria-labelledby="myModalLabel">
        <div className="modal-dialog" role="document">
          <div className="modal-content">
            <div className="modal-header">
              <button type="button" className="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">&times;</span></button>
              <h4 className="modal-title" id="myModalLabel">{t('forms.deleteZone')} ?</h4>
            </div>
            <div className="modal-body">
              {text}
            </div>
            <div className="modal-footer">
              <button type="button"
                      className="btn btn-default"
                      data-dismiss="modal">
                {t('forms.cancel')}
              </button>
              <button type="button"
                      className="btn btn-primary"
                      data-dismiss="modal"
                      onClick={() => this.handleDelete(this.props.zoneId)}
              >{t('forms.delete')}
              </button>
            </div>
          </div>
        </div>
      </div>
    )
  }

}

export default withNamespaces()(ZoneEditor);