diff --git a/app/static/app/js/components/GCPPopup.jsx b/app/static/app/js/components/GCPPopup.jsx new file mode 100644 index 00000000..ff686aae --- /dev/null +++ b/app/static/app/js/components/GCPPopup.jsx @@ -0,0 +1,152 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import AssetDownloads from '../classes/AssetDownloads'; +import '../css/GCPPopup.scss'; +import { _ } from '../classes/gettext'; + +class GCPPopup extends React.Component { + static propTypes = { + feature: PropTypes.object.isRequired, + task: PropTypes.object.isRequired, + }; + + constructor(props){ + super(props); + + this.state = { + error: "", + loading: true, + expandGCPImage: false, + selectedShot: "", + zoom: 1 + } + } + + selectShot = (shotId) => { + if (shotId !== this.state.selectedShot){ + this.setState({loading: true, selectedShot: shotId, error: ""}); + } + } + + _getCoords = (shotId, key) => { + if (!shotId) return [0.5, 0.5]; + + const { feature } = this.props; + const ob = feature.properties.observations.find(o => o.shot_id === shotId); + + if (ob){ + return ob[key]; + }else{ + return [0.5, 0.5]; + } + } + + getAnnotationCoords = (shotId) => { + return this._getCoords(shotId, 'annotated'); + } + + getReprojectedCoords = (shotId) => { + return this._getCoords(shotId, 'reprojected'); + } + + getThumbUrl = (size) => { + const { task } = this.props; + const { selectedShot, zoom } = this.state; + const annotated = this.getAnnotationCoords(selectedShot); + const reprojected = this.getReprojectedCoords(selectedShot); + + return `/api/projects/${task.project}/tasks/${task.id}/images/thumbnail/${selectedShot}?size=${size}¢er_x=${annotated[0]}¢er_y=${annotated[1]}&draw_point=${annotated[0]},${annotated[1]}&point_color=f29900&point_radius=20&draw_point=${reprojected[0]},${reprojected[1]}&&point_color=00ff00&point_radius=20`; + } + + componentDidMount(){ + const { feature } = this.props; + + if (this.image) this.image.addEventListener("fullscreenchange", this.onFullscreenChange); + if (feature.properties.observations) this.selectShot(feature.properties.observations[0].shot_id); + } + + componentWillUnmount(){ + if (this.image) this.image.removeEventListener("fullscreenchange", this.onFullscreenChange); + } + + onFullscreenChange = (e) => { + if (!document.fullscreenElement){ + this.setState({expandGCPImage: false}); + } + } + + imageOnError = () => { + this.setState({error: _("Image missing"), loading: false}); + } + + imageOnLoad = () => { + this.setState({loading: false}); + } + + onImgClick = () => { + const { expandGCPImage } = this.state; + + if (!expandGCPImage){ + this.image.requestFullscreen(); + this.setState({ loading: true, expandGCPImage: true}); + }else{ + document.exitFullscreen(); + this.setState({ expandGCPImage: false }); + } + } + + render(){ + const { error, loading, expandGCPImage, selectedShot, zoom } = this.state; + const { feature, task } = this.props; + + const downloadGCPLink = `/api/projects/${task.project}/tasks/${task.id}/download/ground_control_points.geojson`; + const assetDownload = AssetDownloads.only(["ground_control_points.geojson"])[0]; + const imageUrl = expandGCPImage ? this.getThumbUrl(999999999) : this.getThumbUrl(320); + + const shotLinks = []; + for (let i = 0; i < feature.properties.observations.length; i++){ + const obs = feature.properties.observations[i]; + if (obs.shot_id === selectedShot){ + shotLinks.push({obs.shot_id}); + }else{ + shotLinks.push( this.selectShot(obs.shot_id)}>{obs.shot_id}); + } + if (i+1 < feature.properties.observations.length) shotLinks.push( | ); + } + + const imgStyle = { + borderRadius: "4px" + }; + + return (