import React from 'react'
import getTranslation from '../../../../i18n/'
import AttributeTable from './AttributeTable'
import ReportMaps from './ReportMaps'
import UnitTable from './UnitTable'
import InfoText from './InfoText'
import ReportLegend from './ReportLegend'
import { featureRequest } from '../../helper'
import leafletImage from 'leaflet-image'
import proj4 from 'proj4';
/**
* The report pane. A location based report is shown here
*/
class ReportPane extends React.Component {
constructor(props) {
super(props);
this.state = {
pdfloader: false,
map: undefined,
reportQuery: false,
createBorehole: false
}
}
/**
* Hide the report pane
*/
hidePane() {
this.props.hidePane();
}
/**
* Fetch the report data from the backend via the reportQuery action
* @param {*} map - Reference of the map object
*/
fetchReport(map) {
if((this.props.layers.length > 0) && (this.props.activeArea.uri)){
let bounds = [ map.getBounds().getNorth() , map.getBounds().getEast(), map.getBounds().getSouth(), map.getBounds().getWest() ];
let params = featureRequest(this.props.activeArea.uri, this.props.layers, bounds, [map.getSize().x, map.getSize().y], [map.latLngToContainerPoint([this.props.params.lat, this.props.params.lng]).x, map.latLngToContainerPoint([this.props.params.lat, this.props.params.lng]).y]);
let queryParams = featureRequest(this.props.activeArea.uri, [ this.props.activeLayer ], bounds, [map.getSize().x, map.getSize().y], [map.latLngToContainerPoint([this.props.params.lat, this.props.params.lng]).x, map.latLngToContainerPoint([this.props.params.lat, this.props.params.lng]).y]);
this.props.locationQuery(queryParams, params, this.props.layers, [this.props.params.lat, this.props.params.lng])
this.props.reportQuery(params, this.props.layers, [this.props.params.lat, this.props.params.lng])
this.props.zoomToQuery([this.props.params.lat, this.props.params.lng])
this.setState({reportQuery: true})
}
if(!this.state.map) {
this.setState({ map: map})
}
}
componentWillReceiveProps(nextProps) {
if(!this.state.reportQuery) {
if((nextProps.layers.length > 0) && (nextProps.activeArea.uri)) {
if(this.props.params.lat) {
this.fetchReport(this.state.map)
}
}
}
if((nextProps.fetching.dataFetching.data === 'pdf') && (nextProps.fetching.dataFetching.status)) {
this.setState({ pdfloader: false })
}
}
/**
* Create a PDF report in the backend via the dispatched action
* To create the PDF, the map in the report pane needs to be transitioned to a base64 string
*/
getPDF() {
const html = this.refs.pdf_html.innerHTML;
this.setState({ pdfloader: true })
let activeConflicts = this.props.report.conflicts;
let nonConflicts = this.props.report.non_conflict;
let notes = []
activeConflicts.map(conflict => {
this.props.explanatorynotes.notes.map(note => {
if(note.key === conflict.key) {
notes.push(note)
}
})
})
nonConflicts.map(layer => {
this.props.explanatorynotes.notes.map(note => {
if(note.key === layer.key) {
if(notes.indexOf(note) === -1) {
notes.push(note)
}
}
})
if(layer.children && layer.children.length > 0) {
layer.children.map(child => {
this.props.explanatorynotes.notes.map(note => {
if(note.key === child.key) {
if(notes.indexOf(note) === -1) {
notes.push(note)
}
}
})
})
}
})
// Get the explanatory ynotes
notes.map(note => {
note.name = getTranslation(note.key+".label")
note.description = note['explanatory_note_'+this.props.language.locale] ? note['explanatory_note_'+this.props.language.locale] : note.explanatory_note
})
let mapImage
const mapElement = this.mapRef.leafletElement
// Map to base64 string
leafletImage(mapElement, (err, canvas) => {
mapImage = canvas.toDataURL('image/png');
const headline = this.refs.reporttitle.textContent
const exNotesHeadline = getTranslation("webgis.explanatory_notes")
this.props.generatePDF(headline, html, mapImage, notes, exNotesHeadline);
})
}
componentDidUpdate() {
if(this.props.report.borehole) {
this.loadedBorehole();
}
}
/**
* Create a virtual borehole in the backend
*/
createBorehole() {
const epsg83x = (this.props.activeLayer.reference_system === "ETRS-1989, TM 33-N" ? '+proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs' : '+proj=utm +zone=34 +ellps=GRS80 +units=m +no_defs');
const srs = (this.props.activeLayer.reference_system ==="ETRS-1989, TM 33-N" ? 25833 : 25834);
const convert = proj4(epsg83x, [parseFloat(this.props.report.coords[1]), parseFloat(this.props.report.coords[0])])
const coordinates = 'multipoint z (('+Math.trunc(convert[0])+' '+Math.trunc(convert[1])+' 0))'
this.setState({ createdBorehole: true})
this.props.virtualBorehole(this.props.activeArea.uri, coordinates, srs);
}
/**
* If a borehole is loaded we need to do some stuff do display it properly.
* Texts in the borehole SVG get translated
* The borehole gets filled manually with rectangles between the lines that represent a unit in the borehole
*/
loadedBorehole() {
if(this.props.report.borehole !== false) {
// Need to select some stuff for SVG manipulation
const lines = [].slice.call(document.getElementsByTagName("line"));
const svgElement = [].slice.call(document.getElementsByTagName("svg"))[0];
const units = lines.filter(fil => fil.getAttribute('stroke') != 'rgb(0,0,0)')
const texts = [].slice.call(document.getElementsByTagName("text"));
const names = texts.filter(fil => fil.getAttribute('text-anchor') == 'start')
const meta = texts.filter(fil => fil.getAttribute('text-anchor') == 'middle')
// Needs to be sorted now..
units.sort(function(a,b) {
return b.getAttribute('y1')-a.getAttribute('y1');
})
// Replace the name of the layers in the svg
names.map(name => {
const currentName = name.innerHTML
let titlefield = 'title_'+this.props.language.locale
name.innerHTML = this.props.units.filter(unit => unit.identifier === currentName).length > 0 ? this.props.units.filter(unit => unit.identifier === currentName)[0][titlefield] ? this.props.units.filter(unit => unit.identifier === currentName)[0][titlefield] : this.props.units.filter(unit => unit.identifier === currentName)[0].title_en : currentName;
})
meta.map(me => {
if(me.innerHTML.indexOf("length") !== -1) {
me.innerHTML = me.innerHTML.replace("length", getTranslation("webgis.borehole.length"))
}
if(me.innerHTML.indexOf("bore point") !== -1) {
me.innerHTML = me.innerHTML.replace("bore point", getTranslation("webgis.borehole.point"))
}
})
// Fill the model with color..
var svgNS = "http://www.w3.org/2000/svg";
for(let i = 0; i<units.length; i++) {
if(i+1 < units.length) {
const points = units[i].getAttribute('x1')+","+units[i].getAttribute('y1')+" "+units[i+1].getAttribute('x1')+","+units[i+1].getAttribute('y1')+" "+units[i+1].getAttribute('x2')+","+units[i+1].getAttribute('y2')+" "+units[i].getAttribute('x2')+","+units[i].getAttribute('y2')
let polygon = document.createElementNS(svgNS,"polygon");
polygon.setAttributeNS(null,"points", points);
polygon.setAttributeNS(null,"fill",units[i+1].getAttribute('stroke'));
polygon.setAttributeNS(null,"stroke","none");
svgElement.appendChild(polygon);
}
}
// SVG to PNG for the report because the PDF lib does not support svg..
var stringobJ = new XMLSerializer();
var svg = svgElement;
var svgString = stringobJ .serializeToString(svg );
svg = '<?xml version="1.0"?>\n' + svgString ;
// Creating an Image Element
var image = new Image();
image.src = 'data:image/svg+xml;base64,' + btoa(svg);
// Width and height = width and height from the borehole
image.width = 1000;
image.height = 1950;
// Creating Canvas Element
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
// Create
image.onload = function() {
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0);
const imgstring = canvas.toDataURL('image/png');
if(document.getElementById("borehole_picture")) {
document.getElementById("borehole_picture").src=imgstring;
}
}
}
}
render() {
if(this.props.gisLayers.length > 0) {
this.props.gisLayers.map(layer => {
if(layer.children) {
layer.children.map(child => {
if(child.key === 'existing_boreholes') {
boreholes = true;
boreholeLayer = child;
}
})
}
if(layer.key === 'existing_boreholes') {
boreholes = true;
boreholeLayer = layer;
}
})
}
const units = this.props.units.filter(unit => unit.pilotarea_id === this.props.activeArea.id)
return(
<div className={"report-pane "+(this.props.show? 'show-pane' : 'hide-pane')}>
<button className="close-pane" onClick={() => this.hidePane()}><i className="far fa-times-circle"></i></button>
<h3 className="text-left flexbox-headline">
<span ref="reporttitle"><i className="fas fa-map-marker-alt"></i> {getTranslation("report.title")}</span>
<div className="headline-buttons">
<button onClick={() => this.getPDF()} className="btn btn-red btn-icon btn-pdf">{!this.state.pdfloader ? getTranslation("report.pdf.button") : getTranslation("pdf.generate")}</button>
</div>
</h3>
<div className="width-100">
<ReportMaps mapRef={el => this.mapRef = el} fetchReport={(map) => this.fetchReport(map)} params={this.props.params} query={this.props.query} report={this.props.report} />
</div>
<div ref="pdf_html">
<p className="text-centered">{this.props.report.address}</p>
<div className="width-100 pdf-table">
<div className="width-100 report-flexbox">
<ReportLegend report={this.props.report} />
<div ref="coordinates" className="coordinates text-right">
{this.props.report.coords &&
<React.Fragment>
<p><strong><i className="fas fa-location-arrow"></i> {getTranslation("webgis.coordinates")}:</strong></p>
<p>{Math.round(this.props.report.coords[0] * 10000) / 10000}</p>
<p>{Math.round(this.props.report.coords[1] * 10000) / 10000}</p>
</React.Fragment>
}
</div>
</div>
</div>
<div className="width-100">
<InfoText maps={this.props.report.traffic_light_maps} />
</div>
<div className="width-100">
<div className="attributes-table">
<AttributeTable language={this.props.language} activeLanguage={this.props.activeLanguage} explanatorynotes={this.props.explanatorynotes} report={this.props.report} />
</div>
</div>
{units.length > 0 &&
<React.Fragment>
{(this.props.report.borehole !== '' && this.props.report.borehole !== false) &&
<div className="width-100 contact-details borehole-section">
<h3 className="text-left"><i className="fas fa-pen" aria-hidden="true"></i> <span ref="contact_title">{getTranslation("virtual_borehole.title")}:</span></h3>
<React.Fragment>
<div id="borehole" dangerouslySetInnerHTML={{__html : this.props.report.borehole}}>
</div>
<img id="borehole_picture" src="" />
<UnitTable units={units} language={this.props.language.locale} />
</React.Fragment>
</div>
}
{(this.props.report.borehole === '' || this.props.report.borehole === false) &&
<div className="width-100 contact-details borehole-info">
<h3 className="text-left"><i className="fas fa-pen" aria-hidden="true"></i> <span ref="contact_title">{getTranslation("virtual_borehole.title")}:</span></h3>
<div className="borehole-and-legend">
{this.props.report.borehole === '' &&
<button className="btn btn-green borehole-button" onClick={() => this.createBorehole()}>{getTranslation("webgis.virtual_borehole")}</button>
}
{this.props.report.borehole === false &&
<p>An error occured while creating the virtual borehole.</p>
}
</div>
</div>
}
</React.Fragment>
}
<div className="width-100 contact-details">
<h3 className="text-left"><i className="fa fa-envelope" aria-hidden="true"></i> <span ref="contact_title">{getTranslation("contact.button")}:</span></h3>
{this.props.activeArea.contact_details &&
<span ref="contact_text">
<p dangerouslySetInnerHTML={{__html : this.props.activeArea.contact_details}}></p>
</span>
}
</div>
<div className="width-100 contact-details">
<h3 className="text-left">{getTranslation("report.disclaimer.title")}:</h3>
<p>{getTranslation("report.disclaimer")}</p>
</div>
</div>
</div>
)
}
}
export default ReportPane;