diff --git a/frontend/src/assets/styles/step.scss b/frontend/src/assets/styles/step.scss
index c561ed0..2fef5ea 100644
--- a/frontend/src/assets/styles/step.scss
+++ b/frontend/src/assets/styles/step.scss
@@ -40,3 +40,15 @@
.selected-segment {
background-color: #eeeeee55;
}
+
+.zone-selector-svg path:hover {
+ fill: #eeeeee !important;
+ fill-opacity: 0.5 !important;
+ cursor: pointer;
+}
+
+.zone-selector-svg rect:hover {
+ fill: #eeeeee !important;
+ fill-opacity: 0.5 !important;
+ cursor: pointer;
+}
diff --git a/frontend/src/components/steps/HabitatSVG.jsx b/frontend/src/components/steps/HabitatSVG.jsx
new file mode 100644
index 0000000..4fce2a0
--- /dev/null
+++ b/frontend/src/components/steps/HabitatSVG.jsx
@@ -0,0 +1,27 @@
+import React from 'react';
+
+export const HabitatSVG = ({ name, ...rest }) => {
+ const ImportedIconRef = React.useRef(null);
+ const [loading, setLoading] = React.useState(false);
+
+ React.useEffect(() => {
+ setLoading(true);
+ const importIcon = async () => {
+ try {
+ ImportedIconRef.current = (await import(`!!@svgr/webpack?-svgo,+titleProp,+ref!../../assets/img/habitatSVG/${name}.svg`)).default;
+ } catch (err) {
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ };
+ importIcon();
+ }, [name]);
+
+ if (!loading && ImportedIconRef.current) {
+ const { current: ImportedIcon } = ImportedIconRef;
+ return ;
+ }
+
+ return null;
+};
diff --git a/frontend/src/components/steps/habitat/HabitatSelector.js b/frontend/src/components/steps/habitat/HabitatSelector.js
index 6137bb8..1f308ca 100644
--- a/frontend/src/components/steps/habitat/HabitatSelector.js
+++ b/frontend/src/components/steps/habitat/HabitatSelector.js
@@ -7,6 +7,8 @@ import FormControlLabel from '@mui/material/FormControlLabel';
import FormLabel from '@mui/material/FormLabel';
import FormControl from '@mui/material/FormControl';
import staticText from '../../../assets/data/staticText.json'
+import { HabitatSVG } from '../HabitatSVG'
+
export default function HabitatSelector(props) {
const [habitats, setHabitats] = useState([])
@@ -79,7 +81,7 @@ export default function HabitatSelector(props) {
return (
{image.name}
-
+
)
}
diff --git a/frontend/src/components/steps/zone/ZoneSelector.js b/frontend/src/components/steps/zone/ZoneSelector.js
index 7b47b33..bf02244 100644
--- a/frontend/src/components/steps/zone/ZoneSelector.js
+++ b/frontend/src/components/steps/zone/ZoneSelector.js
@@ -1,36 +1,41 @@
import { useEffect, useState, useRef } from 'react';
-import SampleBackground from '../../../assets/img/stepBackgrounds/step1.jpg';
import SiteRepository from '../../../repository/SiteRepository';
-
+import { HabitatSVG } from '../HabitatSVG'
export default function ZoneSelector(props) {
const [habitatImageObject, setHabitatImageObject] = useState({});
- const [habitatImageFile, setHabitatImageFile] = useState(SampleBackground);
- const [imageHeight, setImageHeight] = useState(0)
+ const [segmentMapping, setSegmentMapping] = useState({});
const [selectedZoneSegment, setZoneSegment] = useState(null);
- const imageContainer = useRef(null)
- const getHabitatImage = (findAndSetImageHeightFunc) => {
+ const getHabitatImage = () => {
SiteRepository.getHabitatImage(props.filters.habitatImage).then(response => {
if (response.status === 200) {
const imageData = response.data
setHabitatImageObject(imageData)
- const imageSrc = require(`../../../assets/img/habitats/${imageData.image_filename}`).default
- setHabitatImageFile(imageSrc)
- findAndSetImageHeightFunc(imageSrc)
}
- }).catch(e => {
- findAndSetImageHeightFunc(habitatImageFile)
})
}
- const setZoneOrRedirect = (zoneSegment) => {
- const redirectHabitat = zoneSegment && zoneSegment.zone && zoneSegment.zone.redirect_habitat;
- setZoneSegment(zoneSegment);
+ const getZones = () => {
+ SiteRepository.getZones().then(response => {
+ if (response.status === 200) {
+ const zoneData = response.data
+ let newSegmentMapping = {}
+ zoneData.forEach(zone => {
+ newSegmentMapping[zone.related_svg_segment] = zone
+ });
+ setSegmentMapping(newSegmentMapping);
+ }
+ })
+ }
+
+ const setZoneOrRedirect = (zone) => {
+ const redirectHabitat = zone && zone.redirect_habitat;
// If there is a redirect habitat set then redirect otherwise set the zone as state
- const newFilterState = redirectHabitat ? { "habitat": { "id": redirectHabitat.id, "name": redirectHabitat.name }} : { "zone": zoneSegment.zone };
+ const newFilterState = redirectHabitat ? { "habitat": { "id": redirectHabitat.id, "name": redirectHabitat.name } } : { "zone": zone };
+
props.updateFilterState(newFilterState);
props.setRedirectBack(Boolean(redirectHabitat));
@@ -38,53 +43,35 @@ export default function ZoneSelector(props) {
}
useEffect(() => {
- // Calculates the image ratio and uses this to calculate the height in pixels based on outer container width
- const findAndSetImageHeight = (imageSource) => {
- let img = new Image();
- img.src = imageSource;
- const newHeight = imageContainer.current ? imageContainer.current.clientWidth * (img.height / img.width) : 0;
- setImageHeight(newHeight);
- }
+ // Retrieves the habitat image from the api if it's not loaded already
+ Object.keys(habitatImageObject).length === 0 && getHabitatImage()
// Retrieves the habitat image from the api if it's not loaded already
- Object.keys(habitatImageObject).length === 0 && getHabitatImage(findAndSetImageHeight)
+ Object.keys(segmentMapping).length === 0 && getZones()
- // Sets the image height such that the full image always displays on page resize
- window.addEventListener("resize", () => findAndSetImageHeight(habitatImageFile), false);
- // Temporarily bypass if there is no image available
- if (props.filters.zone || !props.filters.habitatImage || (habitatImageObject && habitatImageObject.image_segments)) {
- props.setNextDisabled(false);
+ }, [props.filters.zone]);
+
+ const selectZone = (element) => {
+ if (['path', 'rect'].includes(element.tagName) && element.attributes.inkscapelabel && element.attributes.inkscapelabel.nodeValue) {
+ if (selectedZoneSegment) {
+ selectedZoneSegment.style['fill-opacity'] = 0;
+ }
+
+ setZoneSegment(element)
+ element.style.fill = "#eeeeee"
+ element.style['fill-opacity'] = 0.5;
+
+ const zone = segmentMapping[element.attributes.inkscapelabel.nodeValue]
+ setZoneOrRedirect(zone)
}
- });
-
-
- const stepBackground = {
- backgroundImage: `url(${habitatImageFile})`,
- backgroundSize: '100% auto',
- backgroundRepeat: 'none',
- height: imageHeight,
- width: '100%',
- display: 'flex'
}
- return (
-
-
{habitatImageObject && habitatImageObject.name}
- {Object.keys(habitatImageObject).length === 0 ? (
- // Sample segment selector (temporary if no image is available)
-
) :
- // Actual zone selector
- (
- {habitatImageObject && habitatImageObject.image_segments && Array.isArray(habitatImageObject.image_segments) && habitatImageObject.image_segments.map(segment =>
-
{ setZoneOrRedirect(segment) }} className={`selectable-section ${selectedZoneSegment === segment ? 'selected-segment' : ''}`} style={{ width: `${segment.segment_percentage_width}%`, height: '100%' }}>
- )}
-
- )}
-
- )
+ return Object.keys(habitatImageObject).length > 0 ? (
+
+
{habitatImageObject.name}
+
+ selectZone(event.target)} name={habitatImageObject.image_filename} style={{ "height": 'auto', "width": "100%" }} />
+
+
) :
}
diff --git a/frontend/src/repository/Repository.js b/frontend/src/repository/Repository.js
index 9848651..555a907 100644
--- a/frontend/src/repository/Repository.js
+++ b/frontend/src/repository/Repository.js
@@ -2,7 +2,7 @@ import axios from "axios"
// Create the axios object
const repo = axios.create({
- baseURL: window.location.hostname == 'localhost' ? "http://localhost:9000/api" : "/api",
+ baseURL: window.location.hostname === 'localhost' ? "http://localhost:9000/api" : "/api",
});
repo.defaults.headers.post["access-control-allow-origin"] = "*";
diff --git a/frontend/src/repository/SiteRepository.js b/frontend/src/repository/SiteRepository.js
index 08a589f..a3c2b6d 100644
--- a/frontend/src/repository/SiteRepository.js
+++ b/frontend/src/repository/SiteRepository.js
@@ -6,6 +6,10 @@ const SiteRepository = {
return Repository.get(`/habitats/`);
},
+ getZones() {
+ return Repository.get(`/zones/`);
+ },
+
getHabitatImage(habitatImageID) {
return Repository.get(`/habitatimage/${habitatImageID}/`);
}