import React from "react";
import {
createMonitoredArea, deleteMonitoredArea,
fetchMonitoredArea, updateMonitoredArea,
} from '../../restmodules/MonitoredAreaRestModule';
import { fetchDeviceList, fetchUndeployedDeviceList } from '../../restmodules/DeviceRestModule';
import {
ValidateLatitude, ValidateLongitude, ValidateName,
ValidateParameters
} from '../../validationModules/MonitoredAreaFormValidationModule';
import { Redirect } from 'react-router-dom';
import MonitoredAreaMap from '../maps/MonitoredAreaMap';
import '../css/MonitoredAreaAnnotation.css';
import { Checkbox} from 'react-ui-icheck';
import { withNamespaces } from 'react-i18next';
import i18n from '../../../i18n';
/**
* Form for creating new Monitored Area
* @extends Component
* @hideconstructor
*/
class AddMonitoredAreaForm extends React.Component {
/**
* @constructs
* @param props
*/
constructor(props) {
super(props);
this.state = {
isValid : {
name : false,
deviceLatitude : false,
deviceLongitude : false,
device : false
},
monitoredArea : {
"id":"",
"device":
{
"id":""
},
"deviceLatitude":null,
"deviceLongitude":null,
"name":"",
"active":true,
"detectionParameters":
{
"id":"",
"backgroundSubstractionHistory":"1",
"detectorMinContourWidth":"5",
"detectorMinContourHeight":"5",
"counterPathSize":"1",
"counterMaxDistance":"1"
}
},
devices : [],
toMonitoredAreaConfiguration: false,
monitoredAreaFetched : false,
devicesFetched : false
};
this.handleSubmitCreate = this.handleSubmitCreate.bind(this);
this.handleSubmitUpdate = this.handleSubmitUpdate.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
this.handleParametersInputChange = this.handleParametersInputChange.bind(this);
this.handleDeviceInputChange = this.handleDeviceInputChange.bind(this);
this.saveMapLocation = this.saveMapLocation.bind(this);
this.handleDelete = this.handleDelete.bind(this);
if (this.props.match.params.id) {
for (let key in this.state.isValid) {
if (this.state.isValid.hasOwnProperty(key)) {
this.state.isValid[key] = true;
}
}
}
}
/**
* Close form.
*/
closeScreen = () => {
this.setState({
toMonitoredAreaConfiguration: true
});
};
/**
* Set Map Location
* @param lat
* @param lng
*/
saveMapLocation(lat, lng){
let isValid = this.state.isValid;
let data = this.state.monitoredArea;
data.deviceLongitude = lng;
data.deviceLatitude = lat;
isValid.deviceLatitude = ValidateLatitude(data.deviceLatitude);
isValid.deviceLongitude = ValidateLongitude(data.deviceLongitude);
this.setState({
monitoredArea : data,
isValid : isValid
})
}
/**
* Toggle monitoredArea active/archived
*/
toggleActive = () => {
let data = this.state.monitoredArea;
data.active = !this.state.monitoredArea.active;
this.setState({
monitoredArea: data
})
};
/**
*
*/
handleDelete() {
deleteMonitoredArea(this.state.monitoredArea.id)
.then(response => {
if (response.status === 204) {
this.closeScreen();
}
})
.catch(error => console.log(error));
}
/**
*
* @param event
*/
handleSubmitCreate(event) {
let data = this.state.monitoredArea;
// if (this.state.devices.length > 0 && !this.state.monitoredArea.device.id){
// data.device.id = this.state.devices[0].id;
// }
createMonitoredArea(data)
.then(response => {
// this.props.updateTableData();
// this.props.hideMonitoredAreaForm();
this.closeScreen();
});
event.preventDefault();
}
/**
*
* @param event
*/
handleSubmitUpdate(event) {
updateMonitoredArea(this.state.monitoredArea)
.then(response => {
this.closeScreen();
});
event.preventDefault();
}
/**
* Handles name, deviceLatitude, deviceLongitude change.
* @param event
*/
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
let data = this.state.monitoredArea;
data[name] = value;
let isValid = this.state.isValid;
let result;
switch(name) {
case "name":
result = ValidateName(value);
break;
case "deviceLatitude":
result = ValidateLatitude(value);
break;
case "deviceLongitude":
result = ValidateLongitude(value);
this.longitudeDisplayValue = parseFloat(value).toFixed(3);
break;
}
isValid[name] = result;
this.setState({
monitoredArea : data,
isValid : isValid
});
}
/**
* Handles device input change.
* @param event
*/
handleDeviceInputChange(event) {
let data = this.state.monitoredArea;
let isValid = this.state.isValid;
data.device.id = event.target.value;
for (let i = 0; i < this.state.devices.length; i++){
if (this.state.devices[i].id === data.device.id){
data.device.name = this.state.devices[i].name;
break;
}
}
isValid.device = this.isDeviceValid(data.device);
this.setState({
monitoredArea : data,
isValid : isValid
});
}
/**
* Check if device selection is valid
*/
checkDeviceValidity(){
let isValid = this.state.isValid;
isValid.device = this.isDeviceValid(this.state.monitoredArea.device);
this.setState({
isValid : isValid
});
}
/**
* Check if device object is valid
* @param device
* @returns {boolean}
*/
isDeviceValid(device){
return device !== null && device !== undefined && device.id !== undefined && device.id !== null && device.id !== ""
}
/**
* Handle parameters input change
* @param event
*/
handleParametersInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
let data = this.state.monitoredArea;
data.detectionParameters[name] = value;
let isValid = this.state.isValid;
let result;
switch(name) {
case "backgroundSubstractionHistory":
result = ValidateParameters(value, 1, 1000);
break;
case "detectorMinContourHeight":
result = ValidateParameters(value, 1,50);
break;
case "detectorMinContourWidth":
result = ValidateParameters(value, 1,50);
break;
case "counterPathSize":
result = ValidateParameters(value, 1,1000);
break;
case "counterMaxDistance":
result = ValidateParameters(value, 1,100);
break;
default:
}
isValid[name] = result;
this.setState({
monitoredArea : data,
isValid : isValid
}, this.checkDeviceValidity);
}
/**
*
*/
componentDidMount() {
const monitoredAreaID = this.props.match.params.id;
if (monitoredAreaID) {
fetchMonitoredArea(monitoredAreaID)
.then(data => this.setState({ monitoredArea: data }, () => this.setState({ monitoredAreaFetched : true})))
.catch(error => this.setState({ monitoredArea: [{ name: error.toString() }] }));
}
fetchUndeployedDeviceList().then(data => {
data.push({
"id": "",
"name": i18n.t('forms.noCameraSelected')
});
this.setState({ devices: data }, () => this.setState({ devicesFetched: true }))
})
.then()
.catch(error => this.setState({ devices: [{ name: error.toString() }] }));
}
/**
*
* @param prevProps
* @param prevState
* @param snapshot
*/
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.state.monitoredAreaFetched && this.state.devicesFetched){
let devices = this.state.devices;
let contains = false;
for (let i=0; i<devices.length; i++){
if (devices[i].id === this.state.monitoredArea.device.id) {
contains = true;
break;
}
}
if (contains === false) {
devices.push({
"id" : this.state.monitoredArea.device.id,
"name" : this.state.monitoredArea.device.name
});
}
this.setState({
devices: devices,
monitoredAreaFetched : false
});
}
}
/**
*
* @returns {*}
*/
render() {
const { t } = this.props;
if (this.state.toMonitoredAreaConfiguration === true) {
return <Redirect to="/config"/>
}
let submitEnabled = true;
const submitHandle = this.props.match.params.id ? this.handleSubmitUpdate : this.handleSubmitCreate;
for (let key in this.state.isValid) {
if (this.state.isValid.hasOwnProperty(key) && !this.state.isValid[key]) {
submitEnabled = false;
break;
}
}
const title = this.props.match.params.id ? t('forms.update') + ' ' + this.state.monitoredArea.name : t('forms.createNewMonitoredArea');
const bigTitle = this.props.match.params.id ? <h1>
{t('forms.updatingMonitoredArea')}
<small> {t('forms.editMonitoredArea')}</small>
</h1> :
<h1>
{t('forms.additionOfNewMonitoredArea')}
<small> {t('forms.createNewMonitoredArea')}</small>
</h1>
const link = this.props.match.params.id ?
<li><a href={"/config/edit/" + this.state.monitoredArea.id}>{t('forms.updateMonitoredArea')}</a></li> :
<li><a href={"/config/new"}>{t('forms.createMonitoredArea')}</a></li>
return (
<section className="content-header">
{bigTitle}
<ol className="breadcrumb">
<li><a href="/config"><i className="fa fa-gear"></i>{t('sidebar.adminConfiguration')}</a></li>
{link}
</ol>
<br/>
<div className="row">
<div className="col-lg-12">
<div className="box">
{this.renderConfirmDeleteModal(t('forms.deleteMonitoredArea') + "?")}
<div className="box-header with-border">
<h3 className="box-title">{title}</h3>
</div>
<div className="box-header with-border">
<div className=" col-xs-1">
<label>{t('forms.active')}</label>
<label className="control-label fa fa-info-circle info-icon"
data-toggle="tooltip"
title={t('forms.tooltip.active')}/>
</div>
<div className="col-xs-1">
<Checkbox
checkboxClass="icheckbox_square-blue"
checked={this.state.monitoredArea.active}
label=" "
onChange={() => {this.toggleActive()}}
/>
</div>
</div>
<div className="box-body">
<div className={this.state.isValid.device ? "form-group" : "form-group has-error"}>
<label>{t('forms.device')}</label>
<label className="control-label fa fa-info-circle info-icon"
data-toggle="tooltip"
title={t('forms.tooltip.device')}/>
<select className="form-control" name="id" value={this.state.monitoredArea.device.id} onChange={this.handleDeviceInputChange}>
{this.state.devices.map((device, i) =>
<option
value={device.id}
label={device.name}
key={i}
>
{device.name}
</option>
)}
</select>
{this.state.isValid.device ? null : <span className="help-block">{t('forms.help.invalidDeviceSelected')}</span>}
</div>
</div>
<div className="box-body">
<form role="form"
onSubmit={submitHandle}>
<div className={this.state.isValid.name ? "form-group" : "form-group has-error"}>
<label>{t('forms.monitoredAreaName')}</label>
<label className="control-label fa fa-info-circle info-icon"
data-toggle="tooltip"
title={t('forms.tooltip.monitoredAreaName')}/>
<input
type="text"
className="form-control"
placeholder={t("forms.name")}
name="name"
value={this.state.monitoredArea.name}
onChange={this.handleInputChange}
/>
{this.state.isValid.name ? null : <span className="help-block">{t("forms.help.nameCannotBeEmpty")}</span>}
</div>
<div>
<div className="row-xs-flex-center" style={{'margin-right': 'inherit'}}>
<div className="col-sm-2">
<label>{t("forms.coordinates")}</label>
<label className="control-label fa fa-info-circle info-icon"
data-toggle="tooltip"
title={t("forms.tooltip.coordinates")}/>
<div className={this.state.isValid.deviceLatitude ? "form-group" : "form-group has-error"}>
<input
type="text"
className="form-control"
placeholder={t('forms.latitude')}
name="deviceLatitude"
value={this.state.monitoredArea.deviceLatitude}
onChange={this.handleInputChange}
/>
{this.state.isValid.deviceLatitude ? null : <span className="help-block">{t('forms.help.latitude')}</span>}
</div>
<div className={this.state.isValid.deviceLongitude ? "form-group" : "form-group has-error"}>
<input
type="text"
className="form-control"
placeholder={t('forms.longitude')}
name="deviceLongitude"
value={this.state.monitoredArea.deviceLongitude}
onChange={this.handleInputChange}
/>
{this.state.isValid.deviceLongitude ? null : <span className="help-block">{t('forms.help.longitude')}</span>}
</div>
</div>
<div className="col-sm-10">
<MonitoredAreaMap
interactive={true}
saveChanges={(lat, lng) => this.saveMapLocation(lat, lng)}
deviceLatitude={this.state.monitoredArea.deviceLatitude}
deviceLongitude={this.state.monitoredArea.deviceLongitude}
/>
</div>
</div>
</div>
{this.renderSubmitButton(!submitEnabled)}
</form>
</div>
</div>
</div>
</div>
</section>
)
}
renderSubmitButton (disabled){
const { t } = this.props;
if (this.props.match.params.id) {
return (
<div className="box-footer no-border">
<div className="pull-left">
<a
className="btn-link-red"
data-toggle="modal"
data-target="#confirmDeleteModal"
>{t("forms.deleteMonitoredArea")}</a>
</div>
<div className="pull-right">
<button className="btn btn-outline-primary"
onClick={this.closeScreen}
>{t("forms.cancel")}</button>
<button type="submit"
className="btn btn-primary"
disabled={disabled}
>{t("forms.update")}</button>
</div>
</div>
)
}else {
return (
<div className="box-footer no-border">
<div className="pull-right">
<button className="btn btn-default"
onClick={this.closeScreen}
>{t("forms.cancel")}</button>
<button type="submit"
className="btn btn-primary"
disabled={disabled}
>{t("forms.create")}</button>
</div>
</div>
)
}
}
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">×</span></button>
<h4 className="modal-title" id="myModalLabel">{t("forms.deleteMonitoredArea")}?</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}
>{t("forms.delete")}
</button>
</div>
</div>
</div>
</div>
)
}
}
export default withNamespaces()(AddMonitoredAreaForm);