added the construction and aviation map stuff as well as the site api and model
This commit is contained in:
parent
02cee8623a
commit
bcacf761c8
20 changed files with 2549 additions and 9 deletions
757
src/maps/mapObjectControllers/ConstructionMapController.tsx
Normal file
757
src/maps/mapObjectControllers/ConstructionMapController.tsx
Normal file
|
|
@ -0,0 +1,757 @@
|
|||
import {
|
||||
TextField,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
Button,
|
||||
Box,
|
||||
DialogTitle,
|
||||
Autocomplete
|
||||
} from "@mui/material";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import "mapbox-gl/dist/mapbox-gl.css";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useDeviceAPI, useGroupAPI, useMobile, useSnackbar } from "hooks";
|
||||
import { useEffect } from "react";
|
||||
import { useGlobalState, useSiteAPI } from "providers";
|
||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||
import { Device, Group, Site } from "models";
|
||||
// import GroupSettingsIcon from "@material-ui/icons/Settings";
|
||||
import MapBase, { ViewData } from "maps/MapBase";
|
||||
import ConstructionMapTools from "maps/mapObjectTools/constructionMapTools";
|
||||
import { MarkerData } from "maps/mapMarkers/Markers";
|
||||
import { clone } from "lodash";
|
||||
import NexusSTIcon from "products/Construction/NexusSTIcon";
|
||||
import DeviceDrawer from "maps/mapDrawers/DeviceDrawer";
|
||||
//import { Autocomplete } from "@material-ui/lab";
|
||||
import JobsiteIcon from "products/Construction/JobSiteIcon";
|
||||
import SiteDrawer from "maps/mapDrawers/SiteDrawer";
|
||||
import DeviceGroupIcon from "products/Construction/DeviceGroupIcon";
|
||||
import GroupDrawer from "maps/mapDrawers/GroupDrawer";
|
||||
import { Result } from "@mapbox/mapbox-gl-geocoder";
|
||||
//import { GeocoderObject } from "maps/mapControllers/Geocoder";
|
||||
|
||||
interface Props {
|
||||
setSiteCallback?: React.Dispatch<React.SetStateAction<pond.SiteSettings | undefined>>;
|
||||
disableDrawer?: boolean;
|
||||
startingView?: ViewData;
|
||||
}
|
||||
|
||||
export default function ConstructionMapController(props: Props) {
|
||||
const transDuration = 3000;
|
||||
const [{ user, as }] = useGlobalState();
|
||||
const [currentView, setCurrentView] = useState<ViewData>(
|
||||
props.startingView
|
||||
? props.startingView
|
||||
: {
|
||||
latitude: 52.1579,
|
||||
longitude: -106.6702,
|
||||
zoom: user.settings.mapZoom
|
||||
}
|
||||
);
|
||||
const [newLong, setNewLong] = useState(0);
|
||||
const [newLat, setNewLat] = useState(0);
|
||||
const [siteName, setSiteName] = useState("");
|
||||
const siteAPI = useSiteAPI();
|
||||
const [openSiteDrawer, setOpenSiteDrawer] = useState(false);
|
||||
const [SiteDialog, setSiteDialog] = useState(false);
|
||||
const [sites, setSites] = useState<Map<string, Site>>(new Map());
|
||||
const { openSnack } = useSnackbar();
|
||||
const deviceAPI = useDeviceAPI();
|
||||
const [loadingSites, setLoadingSites] = useState(false);
|
||||
const [loadingDevices, setLoadingDevices] = useState(false);
|
||||
//map that is the site id as the key with and array of heater data objects (heaters for that site)
|
||||
const [heaterMap, setHeaterMap] = useState<Map<string, pond.ObjectHeaterData[]>>(
|
||||
new Map<string, pond.ObjectHeaterData[]>()
|
||||
);
|
||||
const groupAPI = useGroupAPI();
|
||||
const [groups, setGroups] = useState<Map<string, Group>>(new Map());
|
||||
const [openMarkerDialog, setOpenMarkerDialog] = useState(false);
|
||||
const [selectKey, setSelectKey] = useState("");
|
||||
const [endTime, setEndTime] = useState(0);
|
||||
const [devOps, setDevOps] = useState<Device[]>([]);
|
||||
const [groupOps, setGroupOps] = useState<Group[]>([]);
|
||||
const [devices, setDevices] = useState<Map<string, Device>>(new Map<string, Device>());
|
||||
const [openDevDrawer, setOpenDevDrawer] = useState(false);
|
||||
const [openGroupDrawer, setOpenGroupDrawer] = useState(false);
|
||||
const [markerType, setMarkerType] = useState<pond.ObjectType>(0);
|
||||
const [devMarkerData, setDevMarkerData] = useState<Map<string, MarkerData>>(new Map());
|
||||
const [siteMarkerData, setSiteMarkerData] = useState<Map<string, MarkerData>>(new Map());
|
||||
const [groupMarkerData, setGroupMarkerData] = useState<Map<string, MarkerData>>(new Map());
|
||||
const [objectKey, setObjectKey] = useState<string>("");
|
||||
const isMobile = useMobile();
|
||||
const [markers, setMarkers] = useState<MarkerData[]>([]);
|
||||
const [displayMarkerTitle, setDisplayMarkerTitle] = useState(false);
|
||||
const zoomLevels = {
|
||||
far: 14,
|
||||
close: 18
|
||||
};
|
||||
const [customGeoSearchEntries, setCustomGeoSearchEntries] = useState<Result[]>([]);
|
||||
const [siteSearchEntries, setSiteSearchEntries] = useState<Result[]>([]);
|
||||
const [deviceSearchEntries, setDeviceSearchEntries] = useState<Result[]>([]);
|
||||
const [groupSearchEntries, setGroupSearchEntries] = useState<Result[]>([]);
|
||||
|
||||
//this click delay is implemented to fix an issue with touch screens that caused the drawer to close immediately after opening
|
||||
const clickDelay = () => {
|
||||
let endTime = new Date().valueOf() + 1000;
|
||||
setEndTime(endTime);
|
||||
};
|
||||
|
||||
const closeDrawers = () => {
|
||||
setOpenDevDrawer(false);
|
||||
setOpenSiteDrawer(false);
|
||||
};
|
||||
|
||||
//makes sure all of the Fields are filled out on the first form of the dialog otherwise the next button is disabled
|
||||
const formComplete = () => {
|
||||
if (siteName.length < 1) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//save the new site to the database
|
||||
const saveSite = () => {
|
||||
let newSite = Site.create();
|
||||
newSite.settings.userId = user.id();
|
||||
newSite.settings.siteName = siteName;
|
||||
newSite.settings.objectKey = user.id();
|
||||
newSite.settings.longitude = newLong;
|
||||
newSite.settings.latitude = newLat;
|
||||
|
||||
siteAPI
|
||||
.addSite(newSite.settings)
|
||||
.then(resp => {
|
||||
openSnack("Added new Site Location");
|
||||
loadSites();
|
||||
})
|
||||
.catch(err => {
|
||||
openSnack("Failed to add site");
|
||||
});
|
||||
setSiteDialog(false);
|
||||
};
|
||||
|
||||
//load the sites from the database and set the markers for each of them
|
||||
const loadSites = useCallback(() => {
|
||||
if (loadingSites) return;
|
||||
setLoadingSites(true);
|
||||
let s: Map<string, Site> = new Map();
|
||||
let sm: Map<string, MarkerData> = new Map();
|
||||
let hMap: Map<string, pond.ObjectHeaterData[]> = new Map<string, pond.ObjectHeaterData[]>();
|
||||
let searchEntries: Result[] = [];
|
||||
siteAPI
|
||||
.listSitesPageData(50, 0, "asc", "key", undefined, as)
|
||||
.then(resp => {
|
||||
resp.data.sites.forEach(site => {
|
||||
if (!site) return;
|
||||
let newSite: Site = Site.any(site.site);
|
||||
s.set(newSite.key(), newSite);
|
||||
//if there is no long/lat on the site give it a default of saskatoon
|
||||
if (!newSite.longitude() || !newSite.latitude()) {
|
||||
newSite.settings.latitude = 52.1579;
|
||||
newSite.settings.longitude = -106.6702;
|
||||
}
|
||||
let siteMarker: MarkerData = {
|
||||
colour: newSite.settings.theme?.color ?? "blue",
|
||||
longitude: newSite.longitude(),
|
||||
latitude: newSite.latitude(),
|
||||
title: newSite.siteName(),
|
||||
markerIcon: <JobsiteIcon type="light" size={50 * 0.6} />,
|
||||
details: [newSite.siteName()],
|
||||
clickFunc: (e, i, isMobile) => {
|
||||
closeDrawers();
|
||||
setObjectKey(newSite.key());
|
||||
setOpenSiteDrawer(true);
|
||||
moveMap(newSite.latitude(), newSite.longitude(), zoomLevels.far, isMobile);
|
||||
},
|
||||
updateFunc: location => {
|
||||
if (newSite.settings) {
|
||||
updateSiteMarkers(newSite, location.longitude, location.latitude);
|
||||
}
|
||||
}
|
||||
};
|
||||
sm.set(newSite.key(), siteMarker);
|
||||
hMap.set(newSite.key(), site.heaterData);
|
||||
searchEntries.push({
|
||||
id: newSite.key(),
|
||||
center: [newSite.longitude(), newSite.latitude()],
|
||||
place_name: newSite.siteName(),
|
||||
place_type: ["site"]
|
||||
} as Result);
|
||||
});
|
||||
setSiteMarkerData(sm);
|
||||
setSites(s);
|
||||
setLoadingSites(false);
|
||||
setHeaterMap(hMap);
|
||||
setSiteSearchEntries(searchEntries);
|
||||
})
|
||||
.catch(err => {
|
||||
openSnack("Failed to load sites");
|
||||
});
|
||||
}, [siteAPI, openSnack, as]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const loadDevices = useCallback(() => {
|
||||
if (loadingDevices) return;
|
||||
setLoadingDevices(true);
|
||||
deviceAPI
|
||||
.list(500, 0, "asc", "name", undefined, undefined, undefined, undefined, undefined, true)
|
||||
.then(resp => {
|
||||
let devOps: Device[] = []; //only devices that are not mapped
|
||||
let deviceMap: Map<string, Device> = new Map<string, Device>(); // all devices
|
||||
let m = clone(devMarkerData);
|
||||
let searchEntries: Result[] = [];
|
||||
resp.data.comprehensiveDevices.forEach(cd => {
|
||||
if (cd.device?.settings?.deviceId) {
|
||||
let dev = Device.any(cd.device);
|
||||
deviceMap.set(dev.id().toString(), dev);
|
||||
let devLoc = dev.location();
|
||||
if (
|
||||
devLoc.longitude &&
|
||||
devLoc.longitude !== 0 &&
|
||||
devLoc.latitude &&
|
||||
devLoc.latitude !== 0
|
||||
) {
|
||||
let devMarker: MarkerData = {
|
||||
colour: dev.settings.theme?.color || "blue",
|
||||
title: dev.name(),
|
||||
longitude: devLoc.longitude,
|
||||
latitude: devLoc.latitude,
|
||||
markerIcon: <NexusSTIcon size={50 * 0.6} type="light" />,
|
||||
details: [dev.name()],
|
||||
clickFunc: (e, i, isMobile) => {
|
||||
closeDrawers();
|
||||
clickDelay();
|
||||
setObjectKey(dev.id().toString());
|
||||
setOpenDevDrawer(true);
|
||||
moveMap(devLoc.latitude, devLoc.longitude, zoomLevels.far, isMobile);
|
||||
},
|
||||
updateFunc: location => {
|
||||
if (dev.settings) {
|
||||
updateDeviceMarkers(dev, location.longitude, location.latitude);
|
||||
}
|
||||
}
|
||||
};
|
||||
m.set(dev.id().toString(), devMarker);
|
||||
searchEntries.push({
|
||||
id: dev.id().toString(),
|
||||
center: [devLoc.longitude, devLoc.latitude],
|
||||
place_name: dev.name(),
|
||||
place_type: ["device"]
|
||||
} as Result);
|
||||
} else {
|
||||
devOps.push(dev);
|
||||
}
|
||||
}
|
||||
});
|
||||
setDevices(deviceMap);
|
||||
setDevOps(devOps);
|
||||
setLoadingDevices(false);
|
||||
setDevMarkerData(m);
|
||||
setDeviceSearchEntries(searchEntries);
|
||||
})
|
||||
.catch(err => {
|
||||
openSnack("Failed to Load Devices");
|
||||
});
|
||||
}, [deviceAPI, openSnack]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const loadGroups = useCallback(() => {
|
||||
groupAPI
|
||||
.listGroups(50, 0)
|
||||
.then(resp => {
|
||||
let gMap: Map<string, Group> = new Map();
|
||||
let groupMarkers: Map<string, MarkerData> = new Map();
|
||||
let groupOps: Group[] = [];
|
||||
let searchEntries: Result[] = [];
|
||||
resp.data.groups.forEach((g: pond.Group) => {
|
||||
let group = Group.any(g);
|
||||
gMap.set(group.id().toString(), group);
|
||||
if (
|
||||
group.settings.longitude &&
|
||||
group.settings.longitude !== 0 &&
|
||||
group.settings.latitude &&
|
||||
group.settings.latitude !== 0
|
||||
) {
|
||||
let marker: MarkerData = {
|
||||
colour: "blue",
|
||||
longitude: group.settings.longitude,
|
||||
latitude: group.settings.latitude,
|
||||
title: group.name(),
|
||||
markerIcon: <DeviceGroupIcon type="light" size={50 * 0.6} />,
|
||||
details: [group.name()],
|
||||
clickFunc: (e, i, isMobile) => {
|
||||
closeDrawers();
|
||||
clickDelay();
|
||||
setObjectKey(group.id().toString());
|
||||
setOpenGroupDrawer(true);
|
||||
moveMap(
|
||||
group.settings.latitude,
|
||||
group.settings.longitude,
|
||||
zoomLevels.far,
|
||||
isMobile
|
||||
);
|
||||
},
|
||||
updateFunc: location => {
|
||||
if (group) {
|
||||
if (group.settings) {
|
||||
let dataClone = clone(groupMarkerData);
|
||||
updateGroupMarkers(group, location.longitude, location.latitude);
|
||||
marker.longitude = location.longitude;
|
||||
marker.latitude = location.latitude;
|
||||
dataClone.set(group.id().toString(), marker);
|
||||
setGroupMarkerData(dataClone);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
groupMarkers.set(group.id().toString(), marker);
|
||||
searchEntries.push({
|
||||
id: group.id().toString(),
|
||||
center: [group.settings.longitude, group.settings.latitude],
|
||||
place_name: group.name(),
|
||||
place_type: ["group"]
|
||||
} as Result);
|
||||
} else {
|
||||
groupOps.push(group);
|
||||
}
|
||||
});
|
||||
setGroups(gMap);
|
||||
setGroupMarkerData(groupMarkers);
|
||||
setGroupOps(groupOps);
|
||||
setGroupSearchEntries(searchEntries);
|
||||
})
|
||||
.catch(err => {
|
||||
//openSnack("Failed to load Groups"); //backend function errors when there are no groups
|
||||
});
|
||||
}, [groupAPI]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
useEffect(() => {
|
||||
loadSites();
|
||||
loadDevices();
|
||||
loadGroups();
|
||||
}, [loadSites, loadDevices, loadGroups, as]);
|
||||
|
||||
//assemble the different objects markerdata into a single array to pass to the map
|
||||
useEffect(() => {
|
||||
let dArray = Array.from(devMarkerData.values());
|
||||
let sArray = Array.from(siteMarkerData.values());
|
||||
let gArray = Array.from(groupMarkerData.values());
|
||||
setMarkers(dArray.concat(sArray, gArray));
|
||||
}, [devMarkerData, siteMarkerData, groupMarkerData]);
|
||||
|
||||
//assemble the different object search entries into one array to pass to the map
|
||||
useEffect(() => {
|
||||
setCustomGeoSearchEntries(siteSearchEntries.concat(deviceSearchEntries, groupSearchEntries));
|
||||
}, [deviceSearchEntries, siteSearchEntries, groupSearchEntries]);
|
||||
|
||||
//the entry fields for the first part of the stepper
|
||||
const siteDetailsForm = () => {
|
||||
return (
|
||||
<Box>
|
||||
<TextField
|
||||
value={siteName}
|
||||
color="primary"
|
||||
autoFocus
|
||||
margin="dense"
|
||||
id="name"
|
||||
label="Site Name"
|
||||
type="text"
|
||||
fullWidth
|
||||
onChange={e => setSiteName(e.target.value)}></TextField>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
//dialog the renders the forms for creating a new site
|
||||
const dialogForSite = () => {
|
||||
return (
|
||||
<ResponsiveDialog
|
||||
fullWidth
|
||||
fullScreen={false}
|
||||
open={SiteDialog}
|
||||
onClose={() => {
|
||||
setSiteDialog(false);
|
||||
}}>
|
||||
<DialogTitle>Enter Name of Site</DialogTitle>
|
||||
<DialogContent>{siteDetailsForm()}</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setSiteDialog(false);
|
||||
}}
|
||||
color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={saveSite} color="primary" disabled={!formComplete()}>
|
||||
Add Site
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
};
|
||||
|
||||
const markerDialog = () => {
|
||||
return (
|
||||
<ResponsiveDialog
|
||||
open={openMarkerDialog}
|
||||
onClose={() => {
|
||||
setOpenMarkerDialog(false);
|
||||
}}>
|
||||
<DialogTitle>Place Marker</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box width={300}>
|
||||
{markerType === pond.ObjectType.OBJECT_TYPE_DEVICE && (
|
||||
<Autocomplete
|
||||
id="autoYardList"
|
||||
options={devOps}
|
||||
getOptionLabel={(option: Device) => option.name()}
|
||||
fullWidth
|
||||
onChange={(e, val) => {
|
||||
val && setSelectKey(val.id().toString());
|
||||
}}
|
||||
renderInput={params => <TextField {...params} label="Device" />}
|
||||
/>
|
||||
)}
|
||||
{markerType === pond.ObjectType.OBJECT_TYPE_GROUP && (
|
||||
<Autocomplete
|
||||
id="autoYardList"
|
||||
options={groupOps}
|
||||
getOptionLabel={(option: Group) => option.name()}
|
||||
fullWidth
|
||||
onChange={(e, val) => {
|
||||
val && setSelectKey(val.id().toString());
|
||||
}}
|
||||
renderInput={params => <TextField {...params} label="Group" />}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Box>
|
||||
<Button onClick={closeNewMarkerDialog}>Cancel</Button>
|
||||
<Button onClick={setMarker}>Plot New Marker</Button>
|
||||
</Box>
|
||||
</DialogActions>
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
};
|
||||
|
||||
const setMarker = () => {
|
||||
if (markerType === pond.ObjectType.OBJECT_TYPE_DEVICE) {
|
||||
let dev = devices.get(selectKey);
|
||||
if (dev) {
|
||||
let key = dev.id().toString();
|
||||
let location = dev.location();
|
||||
let newDevMarker: MarkerData = {
|
||||
colour: dev.settings.theme?.color || "blue",
|
||||
title: dev.name(),
|
||||
longitude: newLong,
|
||||
latitude: newLat,
|
||||
markerIcon: <NexusSTIcon size={50 * 0.6} type="light" />,
|
||||
details: [dev.name()],
|
||||
clickFunc: (e, i, isMobile) => {
|
||||
closeDrawers();
|
||||
clickDelay();
|
||||
setObjectKey(key);
|
||||
setOpenDevDrawer(true);
|
||||
moveMap(location.latitude, location.longitude, zoomLevels.far, isMobile);
|
||||
},
|
||||
updateFunc: location => {
|
||||
if (dev) {
|
||||
if (dev.settings) {
|
||||
let dataClone = clone(devMarkerData);
|
||||
updateDeviceMarkers(dev, location.longitude, location.latitude);
|
||||
newDevMarker.longitude = location.longitude;
|
||||
newDevMarker.latitude = location.latitude;
|
||||
dataClone.set(key, newDevMarker);
|
||||
setDevMarkerData(dataClone);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let devMarkers = clone(devMarkerData);
|
||||
devMarkers.set(key, newDevMarker);
|
||||
setDevMarkerData(devMarkers);
|
||||
updateDeviceMarkers(dev, newLong, newLat);
|
||||
}
|
||||
}
|
||||
if (markerType === pond.ObjectType.OBJECT_TYPE_GROUP) {
|
||||
let group = groups.get(selectKey);
|
||||
if (group) {
|
||||
let key = group.id().toString();
|
||||
let long = group.settings.longitude;
|
||||
let lat = group.settings.latitude;
|
||||
let newMarker: MarkerData = {
|
||||
colour: "blue",
|
||||
title: group.name(),
|
||||
longitude: newLong,
|
||||
latitude: newLat,
|
||||
markerIcon: <DeviceGroupIcon type="light" size={50 * 0.6} />,
|
||||
details: [group.name()],
|
||||
clickFunc: (e, i, isMobile) => {
|
||||
closeDrawers();
|
||||
clickDelay();
|
||||
setObjectKey(key);
|
||||
setOpenGroupDrawer(true);
|
||||
moveMap(lat, long, zoomLevels.far, isMobile);
|
||||
},
|
||||
updateFunc: location => {
|
||||
if (group) {
|
||||
if (group.settings) {
|
||||
let dataClone = clone(groupMarkerData);
|
||||
updateGroupMarkers(group, location.longitude, location.latitude);
|
||||
newMarker.longitude = location.longitude;
|
||||
newMarker.latitude = location.latitude;
|
||||
dataClone.set(key, newMarker);
|
||||
setGroupMarkerData(dataClone);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let groupMarkers = clone(groupMarkerData);
|
||||
groupMarkers.set(key, newMarker);
|
||||
setGroupMarkerData(groupMarkers);
|
||||
updateGroupMarkers(group, newLong, newLat);
|
||||
}
|
||||
}
|
||||
closeNewMarkerDialog();
|
||||
};
|
||||
|
||||
const closeNewMarkerDialog = () => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
setOpenMarkerDialog(false);
|
||||
setSelectKey("");
|
||||
}
|
||||
};
|
||||
|
||||
const updateDeviceMarkers = (device: Device, long: number, lat: number) => {
|
||||
device.settings.longitude = long;
|
||||
device.settings.latitude = lat;
|
||||
deviceAPI
|
||||
.update(device.id(), device.settings)
|
||||
.then(resp => {
|
||||
openSnack("Device location Updated");
|
||||
if (devOps.includes(device)) {
|
||||
devOps.splice(devOps.indexOf(device), 1);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
openSnack("Could not update Device Location");
|
||||
});
|
||||
};
|
||||
|
||||
const updateGroupMarkers = (group: Group, long: number, lat: number) => {
|
||||
group.settings.longitude = long;
|
||||
group.settings.latitude = lat;
|
||||
groupAPI
|
||||
.updateGroup(group.id(), group.settings)
|
||||
.then(resp => {
|
||||
openSnack("Group location Updated");
|
||||
if (groupOps.includes(group)) {
|
||||
groupOps.splice(groupOps.indexOf(group), 1);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
openSnack("Could not update Group Location");
|
||||
});
|
||||
};
|
||||
|
||||
const updateSiteMarkers = (site: Site, long: number, lat: number) => {
|
||||
site.settings.longitude = long;
|
||||
site.settings.latitude = lat;
|
||||
siteAPI
|
||||
.updateSite(site.key(), site.settings)
|
||||
.then(resp => {
|
||||
openSnack("Site location updated");
|
||||
})
|
||||
.catch(err => {
|
||||
openSnack("Could not update site location");
|
||||
});
|
||||
};
|
||||
|
||||
const moveMap = (
|
||||
lat: number,
|
||||
long: number,
|
||||
zoom: number,
|
||||
mobileOffset?: boolean,
|
||||
center?: boolean
|
||||
) => {
|
||||
let xOff = !mobileOffset ? -250 : undefined;
|
||||
let yOff = mobileOffset ? -150 : undefined;
|
||||
|
||||
setCurrentView({
|
||||
latitude: lat,
|
||||
longitude: long,
|
||||
zoom: zoom,
|
||||
transitionDuration: transDuration,
|
||||
xOffset: center ? 0 : xOff,
|
||||
yOffset: center ? 0 : yOff
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Box style={{ height: "100%" }}>
|
||||
<MapBase
|
||||
placingMarker={markerType !== pond.ObjectType.OBJECT_TYPE_UNKNOWN}
|
||||
displayMarkerTitles={displayMarkerTitle}
|
||||
customSearchEntries={customGeoSearchEntries}
|
||||
geocoderResultFunction={result => {
|
||||
//open drawer
|
||||
setObjectKey(result.id?.toString() ?? "");
|
||||
if (result.place_type.includes("site")) {
|
||||
setOpenSiteDrawer(true);
|
||||
} else if (result.place_type.includes("device")) {
|
||||
setOpenDevDrawer(true);
|
||||
} else if (result.place_type.includes("group")) {
|
||||
setOpenGroupDrawer(true);
|
||||
}
|
||||
}}
|
||||
geocoderTransitionFunction={result => {
|
||||
//override the geocoders transition with our own
|
||||
let long = result.center[0];
|
||||
let lat = result.center[1];
|
||||
if (long && lat) {
|
||||
let centered = true;
|
||||
let zoom = zoomLevels.far;
|
||||
if (
|
||||
result.place_type.includes("site") ||
|
||||
result.place_type.includes("device") ||
|
||||
result.place_type.includes("group")
|
||||
) {
|
||||
centered = false;
|
||||
}
|
||||
moveMap(lat, long, zoom, isMobile, centered);
|
||||
}
|
||||
}}
|
||||
mapTools={
|
||||
<ConstructionMapTools
|
||||
toggleMarkerType={setMarkerType}
|
||||
toggleMarkerDisplay={setDisplayMarkerTitle}
|
||||
/>
|
||||
}
|
||||
mapClick={e => {
|
||||
if (markerType !== pond.ObjectType.OBJECT_TYPE_UNKNOWN) {
|
||||
setNewLong(e.lngLat.lng);
|
||||
setNewLat(e.lngLat.lat);
|
||||
if (markerType === pond.ObjectType.OBJECT_TYPE_SITE) {
|
||||
setSiteDialog(true);
|
||||
} else {
|
||||
setOpenMarkerDialog(true);
|
||||
}
|
||||
}
|
||||
}}
|
||||
currentView={currentView}
|
||||
markerData={markers}
|
||||
/>
|
||||
{dialogForSite()}
|
||||
{markerDialog()}
|
||||
{objectKey !== "" && (
|
||||
<React.Fragment>
|
||||
<DeviceDrawer
|
||||
open={openDevDrawer}
|
||||
onClose={() => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
setOpenDevDrawer(false);
|
||||
setObjectKey("");
|
||||
}
|
||||
}}
|
||||
selectedDevice={objectKey}
|
||||
devices={devices}
|
||||
removeMarker={key => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
//use the key to remove it from the map of yard markers which should cause the markerData array to update
|
||||
let newMarkers = clone(devMarkerData);
|
||||
newMarkers.delete(key);
|
||||
setDevMarkerData(newMarkers);
|
||||
//adds it back to the options
|
||||
let dev = devices.get(key);
|
||||
if (dev) {
|
||||
devOps.push(dev);
|
||||
}
|
||||
}
|
||||
}}
|
||||
updateMarker={(key, objectSettings) => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
let newMarkers = clone(devMarkerData);
|
||||
let toupdate = newMarkers.get(key);
|
||||
if (toupdate) {
|
||||
if (objectSettings.theme) {
|
||||
toupdate.colour = objectSettings.theme.color;
|
||||
}
|
||||
}
|
||||
setDevMarkerData(newMarkers);
|
||||
}
|
||||
}}
|
||||
moveMap={(long, lat) => {
|
||||
moveMap(lat, long, zoomLevels.far, isMobile);
|
||||
}}
|
||||
/>
|
||||
<SiteDrawer
|
||||
open={openSiteDrawer}
|
||||
sites={sites}
|
||||
heaters={heaterMap}
|
||||
selectedSite={objectKey}
|
||||
onClose={() => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
setOpenSiteDrawer(false);
|
||||
setObjectKey("");
|
||||
}
|
||||
}}
|
||||
moveMap={(long, lat) => {
|
||||
moveMap(lat, long, zoomLevels.far, isMobile);
|
||||
}}
|
||||
removeMarker={key => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
//use the key to remove it from the map of yard markers which should cause the markerData array to update
|
||||
let newMarkers = clone(siteMarkerData);
|
||||
newMarkers.delete(key);
|
||||
setSiteMarkerData(newMarkers);
|
||||
}
|
||||
}}
|
||||
updateMarker={(key, objectSettings) => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
let newMarkers = clone(siteMarkerData);
|
||||
let toupdate = newMarkers.get(key);
|
||||
if (toupdate) {
|
||||
if (objectSettings.theme) {
|
||||
toupdate.colour = objectSettings.theme.color;
|
||||
}
|
||||
}
|
||||
setSiteMarkerData(newMarkers);
|
||||
}
|
||||
}}
|
||||
reLoadSites={() => {
|
||||
loadSites();
|
||||
}}
|
||||
/>
|
||||
<GroupDrawer
|
||||
open={openGroupDrawer}
|
||||
groups={groups}
|
||||
moveMap={(long, lat) => {
|
||||
moveMap(lat, long, zoomLevels.far, isMobile);
|
||||
}}
|
||||
onClose={() => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
setOpenGroupDrawer(false);
|
||||
setObjectKey("");
|
||||
}
|
||||
}}
|
||||
removeMarker={key => {
|
||||
if (new Date().valueOf() > endTime) {
|
||||
//use the key to remove it from the map of yard markers which should cause the markerData array to update
|
||||
let newMarkers = clone(groupMarkerData);
|
||||
newMarkers.delete(key);
|
||||
setGroupMarkerData(newMarkers);
|
||||
//adds it back to the options
|
||||
let group = groups.get(key);
|
||||
if (group) {
|
||||
groupOps.push(group);
|
||||
}
|
||||
}
|
||||
}}
|
||||
selectedGroup={objectKey}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue