{"version":3,"sources":["Assets/map.png","Assets/Icons/Map_main.svg","Assets/Icons/Favourite_active.svg","Assets/Fonts/Audiowide.ttf","Assets/Fonts/Montserrat-Regular.ttf","Assets/Fonts/Montserrat-Bold.ttf","Assets/Fonts/Montserrat-SemiBold.ttf","Assets/Icons/InnerBox_Search.svg","Assets/Icons/Rename.svg","Assets/Icons/InnerBox_Left.svg","Assets/Icons/InnerBox_Right.svg","Assets/Icons/Calendar.svg","Assets/Icons/Analysis.svg","Assets/Icons/Logout.svg","Assets/Icons/Help.svg","Assets/Icons/3DMapping.svg","Assets/Icons/Heatmap.svg","Assets/Icons/pathIcon.svg","Assets/Icons/InnerBox_Down.svg","Assets/Icons/InnerBox_Up.svg","Assets/Icons/close.png","Assets/Icons/AVG_Callout.svg","Assets/Icons/exportData.svg","Assets/Icons/InnerBox_Sync.svg","Assets/loginVideo.m4v","Assets/Icons/Login.svg","Assets/Icons/Mail.svg","Assets/Icons/youtube.svg","Assets/Icons/linkedin.svg","Assets/Icons/twitter.svg","Assets/Icons/instagram.svg","Assets/Icons/facebook.svg","Assets/404.gif","serviceWorker.js","Containers/Context/auth.js","Containers/PrivateRoute.js","Containers/Styles.js","Containers/Select.js","Containers/Calendar.js","Containers/calls.js","Containers/utility.js","Pages/Home.js","Containers/Guide.js","Containers/Navbar.js","Containers/GoogleMap.js","Containers/Sensor.js","Containers/Export.js","Pages/Project.js","Containers/LineChart.js","Pages/Analysis.js","Pages/Alerts.js","Pages/CustomStyles/Login.js","Pages/Login.js","Pages/NotFound.js","App.js","index.js"],"names":["module","exports","Boolean","window","location","hostname","match","AuthContext","createContext","useAuth","useContext","PrivateRoute","Component","component","rest","authToken","props","to","pathname","state","from","colors","Fonts","createGlobalStyle","Audiowide","MontserratRegular","MontserratSemiBold","MontserratBold","expand","keyframes","slide_up","reverse_slide_up","slide_right","reverse_slide_right","GuideStyle","CompanyLabel","styled","label","fontSize","colStart","colEnd","textAlign","Main","div","Page","bgImg","ContentWrap","AlertsWrap","AnalysisWrap","ProjectWrap","NotFoundWrap","Input","input","height","bg","MenuInput","Search","searchIcon","Button","renameIcon","button","width","justify","theme","main","align","defaultProps","SecondaryButton","icon","Error","color","warning","default","margin","Ul","ul","gap","maxHeight","alignContent","Nav","Li","li","NavLi","pointerEvents","brightness","GridLi","display","selected","Img","img","top","pointer","right","pos","webkitFilter","objectFit","zindex","Menu","hide","ProjectMenus","NodeMenu","FlightMenu","HomeMenu","AlertsMenu","StyledLink","Link","RowCheckbox","LastSync","span","AlertWindow","AlertHeader","Circle","ChartStyle","Sensors","Gauge","fill","turn","MarkerButton","attrs","tabIndex","MaxIntensController","Select","styles","control","base","background","black","borderRadius","boxShadow","borderColor","cursor","singleValue","placeholder","fontFamily","indicatorSeparator","menu","padding","zIndex","menuList","option","backgorundColor","backgroundColor","isSelected","Calendar","date","chevronLeft","chevronRight","selectedDays","onDayClick","day","setHours","setDate","DateUtils","addDayToRange","modifiers","myHeaders","Accept","doFetch","method","path","signal","data","a","localStorage","token","url","options","body","JSON","stringify","credentials","headers","fetch","resp","ok","json","status","text","err","statusText","dateParser","timestamp","fullFormat","seconds","Date","string","getMonth","slice","getDate","getFullYear","hours","getHours","mins","getMinutes","getSeconds","Home","console","log","resetTokens","useState","projects","setProjects","drones","setDrones","selectedProject","setSelectedProject","search","dropdown","undefined","favourites","filter","setFilter","useEffect","then","catch","timeout","setTimeout","Math","floor","getTime","clearTimeout","className","left","autoComplete","onChange","event","target","value","trim","toLowerCase","map","drone","serial_number","id","isClearable","d","flightDates","concat","project","travel_sessions","ts","start_timestamp","end_timestamp","htmlFor","type","checked","prj","i","key","onClick","e","name","src","favActive","style","is_favourite","stopPropagation","length","time_length","setItem","removeItem","Guide","guideState","setGuideState","currentPage","getItem","setStepHook","title","guideIcon","alt","ref","step","enabled","steps","drimsGuide","onBeforeChange","nextStepIndex","mapControls","document","querySelector","marker","click","children","alerts","initialStep","onExit","Navbar","projectId","useLocation","listItems","MenuIcon","link","ProjectIcon","AnalysisIcon","item","logOut","LogoutIcon","GoogleMap","mapRef","useRef","mapsRef","zoom","setZoom","ne","lat","lng","nw","se","sw","bounds","setBounds","mapType","setMapType","activeControl","setActiveControl","flightPath","setFlightPath","mapPoints","setPoints","heatmapData","setHeatmapData","heatmapInstance","setHeatmapInstance","setCustomMax","limit","heatmapSensor","setHeatmapSensor","validationSchema","Yup","shape","max","required","min","typeError","formOptions","mode","resolver","yupResolver","useForm","register","handleSubmit","reset","errors","formState","setMap","flight","samples","points","node","properties","cluster","nodeId","values","altitude","sensor_name","geometry","coordinates","longitude","latitude","current","flightBounds","LatLngBounds","extend","fitBounds","p","Polyline","geodesic","strokeColor","strokeOpacity","strokeWeight","aq_limit","sensors","apply","o","controlsWrap","controls","ControlPosition","TOP_CENTER","removeChild","createElement","gridColumn","border","transition","classList","add","innerText","disabled","hidden","appendChild","addEventListener","sensor","heatmapInst","visualization","HeatmapLayer","dissipating","radius","opacity","maxIntensity","setOptions","initHeatPositions","weight","uniquePositions","closePoints","j","lngDiff","latDiff","sqrt","pow","push","unique","splice","indexOf","heatPositions","heatmapPoint","LatLng","setTilt","btn","setNodeInfo","useSupercluster","maxZoom","clusters","supercluster","createOptions","useCallback","maps","restriction","latLngBounds","north","south","west","east","elementType","stylers","featureType","visibility","mapTypeControl","rotateControl","mapTypeControlOptions","position","BOTTOM_CENTER","mapTypeIds","MapTypeId","SATELLITE","ROADMAP","mapTypeId","fullscreenControlOptions","BOTTOM_RIGHT","minZoom","markerOnClick","info","compareCoords","coords","nodeCoords","selectedCoords","bootstrapURLKeys","libraries","defaultCenter","defaultZoom","yesIWantToUseGoogleMapApiInternals","onGoogleApiLoaded","controlDiv","defaultMapBtn","heatMapBtn","map3dBtn","flightPathBtn","justifyContent","index","defImg","heatImg","d3Img","pathImg","setAttribute","defaultMapIcon","heatmapIcon","map3dIcon","pathIcon","gridTemplateColumns","gridTemplateRows","marginTop","createMapControls","onMapTypeIdChange","isCluster","pointCount","point_count","leaves","getLeaves","Infinity","avg","parse","l","avgTemp","avgHumid","avgPressure","chartValues","onSubmit","alert","message","Sensor","val","unit","percent","chartWidth","percentToHue","avgIcon","toFixed","Export","units","offset","timezone","buildNodeData","csv","timestampWithOffset","buildFlightData","encodedUri","encodeURI","remove","exportData","Project","params","flightId","setProject","setFlight","selectedFlight","setSelectedFlight","nodeInfo","displayFlightmenuFlag","setDisplayFlightmenuFlag","abortControl","AbortController","reqUrl","updateNodeInfo","abort","closeTab","timestampArray","point","first","last","substring","dateStr","displaySensorHeader","s","Object","fromEntries","timezone_offset","timezone_id","f","distance","reduce","t","ceil","defaultValue","flightList","defaultChecked","upShevron","downShevron","LineChart","flightData","legendFlag","am4core","am4themes_dark","chart","addSeries","ch","yAxes","line","series","am4charts","dataFields","dateX","stroke","valueY","strokeWidth","tooltipText","yAxis","events","on","addYAxis","yAxisLocation","valueAxis","renderer","opposite","tooltip","layout","rotation","valign","dy","dx","labels","template","grid","useLayoutEffect","autoSetClassName","sample","dateAxis","xAxes","groupData","sameUnitFlag","toggle","show","addToggleSensors","legend","dispose","Analysis","chartLegendFlag","setChartLegendFlag","overflow","Alerts","1598102170109","1598127446160","1597786892009","1597777773945","unreadFilter","setUnreadFilter","activeAlert","setActiveAlert","syncIcon","keys","read","liClickHandle","header","marginRight","Form","form","FormWrap","Video","video","Login","loginError","setLoginError","setWarning","setAuthToken","loginIcon","href","autoPlay","loop","muted","loginVid","mailIcon","twit","yt","ig","fb","NotFound","gifImage","datadogRum","init","applicationId","clientToken","site","service","sampleRate","premiumSampleRate","trackInteractions","defaultPrivacyLevel","startSessionReplayRecording","App","userToken","clear","Provider","active","exact","ReactDOM","render","getElementById","navigator","serviceWorker","ready","registration","unregister","error"],"mappings":"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","file":"static/js/main.e62f3cda.chunk.js","sourcesContent":["module.exports = __webpack_public_path__ + \"static/media/map.d482ec08.png\";","module.exports = __webpack_public_path__ + \"static/media/Map_main.05634243.svg\";","module.exports = __webpack_public_path__ + \"static/media/Favourite_active.0d38297e.svg\";","module.exports = __webpack_public_path__ + \"static/media/Audiowide.e9ee108c.ttf\";","module.exports = __webpack_public_path__ + \"static/media/Montserrat-Regular.ee653992.ttf\";","module.exports = __webpack_public_path__ + \"static/media/Montserrat-Bold.ade91f47.ttf\";","module.exports = __webpack_public_path__ + \"static/media/Montserrat-SemiBold.c641dbee.ttf\";","module.exports = __webpack_public_path__ + \"static/media/InnerBox_Search.d3559471.svg\";","module.exports = __webpack_public_path__ + \"static/media/Rename.cbffc5cc.svg\";","module.exports = __webpack_public_path__ + \"static/media/InnerBox_Left.9d08d1a7.svg\";","module.exports = __webpack_public_path__ + \"static/media/InnerBox_Right.e93e92d4.svg\";","module.exports = __webpack_public_path__ + \"static/media/Calendar.de5de665.svg\";","module.exports = __webpack_public_path__ + \"static/media/Analysis.5a1ce58b.svg\";","module.exports = __webpack_public_path__ + \"static/media/Logout.b5cdd841.svg\";","module.exports = __webpack_public_path__ + \"static/media/Help.e03c1d1c.svg\";","module.exports = __webpack_public_path__ + \"static/media/3DMapping.3690a33d.svg\";","module.exports = __webpack_public_path__ + \"static/media/Heatmap.7172faac.svg\";","module.exports = __webpack_public_path__ + \"static/media/pathIcon.65934b03.svg\";","module.exports = __webpack_public_path__ + \"static/media/InnerBox_Down.14478f25.svg\";","module.exports = __webpack_public_path__ + \"static/media/InnerBox_Up.4b72b284.svg\";","module.exports = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAQAAACR313BAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAAAEgAAABIAEbJaz4AAAB4SURBVBjThZHBDYNADAQHhEQPXE1xLTQRugPRAog6MnmgiMCFi3/2jmV7DdCSqDlHTaIFaOidiYsczvQ0kJzU7QSEmzrSHckBfPIHl0L8gL+AxadLLu7Aqr7UNRehcnCPgSqXi93F2cXN7+4OgM7xxrWJ9Nfz4sfeBXKPJBCd/SkAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTgtMTAtMzFUMTI6MjM6MTEtMDQ6MDAmQaEDAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE4LTEwLTMxVDEyOjIzOjExLTA0OjAwVxwZvwAAAABJRU5ErkJggg==\"","module.exports = __webpack_public_path__ + \"static/media/AVG_Callout.71f969de.svg\";","module.exports = __webpack_public_path__ + \"static/media/exportData.023546ff.svg\";","module.exports = __webpack_public_path__ + \"static/media/InnerBox_Sync.9e4c2ada.svg\";","module.exports = __webpack_public_path__ + \"static/media/loginVideo.114880b0.m4v\";","module.exports = __webpack_public_path__ + \"static/media/Login.be48a34f.svg\";","module.exports = __webpack_public_path__ + \"static/media/Mail.edab07d7.svg\";","module.exports = __webpack_public_path__ + \"static/media/youtube.7d44f482.svg\";","module.exports = __webpack_public_path__ + \"static/media/linkedin.23cefbfa.svg\";","module.exports = __webpack_public_path__ + \"static/media/twitter.1a7ca2da.svg\";","module.exports = __webpack_public_path__ + \"static/media/instagram.d754fc24.svg\";","module.exports = __webpack_public_path__ + \"static/media/facebook.d8df5b5d.svg\";","module.exports = __webpack_public_path__ + \"static/media/404.8e304055.gif\";","// This optional code is used to register a service worker.\r\n// register() is not called by default.\r\n\r\n// This lets the app load faster on subsequent visits in production, and gives\r\n// it offline capabilities. However, it also means that developers (and users)\r\n// will only see deployed updates on subsequent visits to a page, after all the\r\n// existing tabs open on the page have been closed, since previously cached\r\n// resources are updated in the background.\r\n\r\n// To learn more about the benefits of this model and instructions on how to\r\n// opt-in, read https://bit.ly/CRA-PWA\r\n\r\nconst isLocalhost = Boolean(\r\n window.location.hostname === 'localhost' ||\r\n // [::1] is the IPv6 localhost address.\r\n window.location.hostname === '[::1]' ||\r\n // 127.0.0.0/8 are considered localhost for IPv4.\r\n window.location.hostname.match(\r\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\r\n )\r\n);\r\n\r\nexport function register(config) {\r\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\r\n // The URL constructor is available in all browsers that support SW.\r\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\r\n if (publicUrl.origin !== window.location.origin) {\r\n // Our service worker won't work if PUBLIC_URL is on a different origin\r\n // from what our page is served on. This might happen if a CDN is used to\r\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\r\n return;\r\n }\r\n\r\n window.addEventListener('load', () => {\r\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\r\n\r\n if (isLocalhost) {\r\n // This is running on localhost. Let's check if a service worker still exists or not.\r\n checkValidServiceWorker(swUrl, config);\r\n\r\n // Add some additional logging to localhost, pointing developers to the\r\n // service worker/PWA documentation.\r\n navigator.serviceWorker.ready.then(() => {\r\n console.log(\r\n 'This web app is being served cache-first by a service ' +\r\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\r\n );\r\n });\r\n } else {\r\n // Is not localhost. Just register service worker\r\n registerValidSW(swUrl, config);\r\n }\r\n });\r\n }\r\n}\r\n\r\nfunction registerValidSW(swUrl, config) {\r\n navigator.serviceWorker\r\n .register(swUrl)\r\n .then(registration => {\r\n registration.onupdatefound = () => {\r\n const installingWorker = registration.installing;\r\n if (installingWorker == null) {\r\n return;\r\n }\r\n installingWorker.onstatechange = () => {\r\n if (installingWorker.state === 'installed') {\r\n if (navigator.serviceWorker.controller) {\r\n // At this point, the updated precached content has been fetched,\r\n // but the previous service worker will still serve the older\r\n // content until all client tabs are closed.\r\n console.log(\r\n 'New content is available and will be used when all ' +\r\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\r\n );\r\n\r\n // Execute callback\r\n if (config && config.onUpdate) {\r\n config.onUpdate(registration);\r\n }\r\n } else {\r\n // At this point, everything has been precached.\r\n // It's the perfect time to display a\r\n // \"Content is cached for offline use.\" message.\r\n console.log('Content is cached for offline use.');\r\n\r\n // Execute callback\r\n if (config && config.onSuccess) {\r\n config.onSuccess(registration);\r\n }\r\n }\r\n }\r\n };\r\n };\r\n })\r\n .catch(error => {\r\n console.error('Error during service worker registration:', error);\r\n });\r\n}\r\n\r\nfunction checkValidServiceWorker(swUrl, config) {\r\n // Check if the service worker can be found. If it can't reload the page.\r\n fetch(swUrl, {\r\n headers: { 'Service-Worker': 'script' },\r\n })\r\n .then(response => {\r\n // Ensure service worker exists, and that we really are getting a JS file.\r\n const contentType = response.headers.get('content-type');\r\n if (\r\n response.status === 404 ||\r\n (contentType != null && contentType.indexOf('javascript') === -1)\r\n ) {\r\n // No service worker found. Probably a different app. Reload the page.\r\n navigator.serviceWorker.ready.then(registration => {\r\n registration.unregister().then(() => {\r\n window.location.reload();\r\n });\r\n });\r\n } else {\r\n // Service worker found. Proceed as normal.\r\n registerValidSW(swUrl, config);\r\n }\r\n })\r\n .catch(() => {\r\n console.log(\r\n 'No internet connection found. App is running in offline mode.'\r\n );\r\n });\r\n}\r\n\r\nexport function unregister() {\r\n if ('serviceWorker' in navigator) {\r\n navigator.serviceWorker.ready\r\n .then(registration => {\r\n registration.unregister();\r\n })\r\n .catch(error => {\r\n console.error(error.message);\r\n });\r\n }\r\n}\r\n","import { createContext, useContext } from 'react';\r\n\r\nexport const AuthContext = createContext();\r\n\r\nexport function useAuth() {\r\n return useContext(AuthContext);\r\n}\r\n","import React from 'react';\r\nimport { Route, Redirect } from 'react-router-dom';\r\nimport { useAuth } from './Context/auth';\r\n\r\n// Redirects to login, if not authenticated\r\nexport default function PrivateRoute({ component: Component, ...rest }) {\r\n const { authToken } = useAuth();\r\n\r\n return (\r\n (\r\n authToken ? (\r\n \r\n ) : (\r\n \r\n )\r\n )} />\r\n );\r\n}\r\n","import styled, { createGlobalStyle, keyframes } from \"styled-components\";\nimport Audiowide from '../Assets/Fonts/Audiowide.ttf';\nimport MontserratRegular from '../Assets/Fonts/Montserrat-Regular.ttf';\nimport MontserratBold from '../Assets/Fonts/Montserrat-Bold.ttf';\nimport MontserratSemiBold from '../Assets/Fonts/Montserrat-SemiBold.ttf';\nimport searchIcon from '../Assets/Icons/InnerBox_Search.svg';\nimport renameIcon from '../Assets/Icons/Rename.svg';\nimport bgImg from '../Assets/map.png';\nimport { Link } from 'react-router-dom';\n\nexport const colors = {\n mainRed: 'rgb(227, 50, 46)',\n mainGrey: 'rgb(217,215,215)',\n mainBlack: 'rgb(24,22,25)',\n mainHover: 'rgba(150,150,150,.4)',\n mainYellow: '#F9B513'\n}\n\n// Fonts\nexport const Fonts = createGlobalStyle`\n @font-face {\n font-family: Audiowide;\n src: url(${Audiowide});\n }\n @font-face {\n font-family: Montserrat;\n src: url(${MontserratRegular});\n }\n @font-face {\n font-family: MontserratSemiBold;\n src: url(${MontserratSemiBold});\n font-weight: semi-bold;\n }\n @font-face {\n font-family: MontserratBold;\n src: url(${MontserratBold});\n font-weight: bold;\n }\n`;\n\n// keyframes \nconst expand = keyframes`\n from {\n transform: scale(0);\n }\n`;\nconst slide_up = keyframes`\n 0% {\n transform: translateY(0%);\n }\n 100% {\n transform: translateY(-100%);\n }\n`;\nconst reverse_slide_up = keyframes`\n 0% {\n transform: translateY(-100%);\n }\n 100% {\n transform: translateY(0%);\n }\n`;\nconst slide_right = keyframes`\n 0% {\n transform: translateX(0%);\n }\n 100% {\n transform: translateX(-100%);\n }\n`;\nconst reverse_slide_right = keyframes`\n 0% {\n transform: translateX(-100%);\n }\n 100% {\n transform: translateX(0%);\n }\n`;\n\n// Custom font application for introjs tooltip\nexport const GuideStyle = createGlobalStyle`\n .introjs-tooltip, .introjs-button {\n font-family: Montserrat !important;\n }\n`;\n\nexport const CompanyLabel = styled.label`\n font-family: Audiowide;\n font-size: ${ props => props.fontSize };\n grid-column-start: ${ props => props.colStart };\n grid-column-end: ${ props => props.colEnd };\n text-align: ${ props => props.textAlign };\n`;\n\n// Pages\nexport const Main = styled.div`\n display: grid;\n grid-template-columns: 4rem 1fr;\n min-height: 100%;\n min-width: 100%;\n position: absolute;\n top: 0;\n left: 0;\n background-color: rgb(35,35,35);\n font-family: Montserrat;\n`;\nexport const Page = styled.div`\n position: relative;\n\n &::before {\n content: '';\n background-image: url(${bgImg});\n filter: blur(2rem);\n position: absolute;\n width: 100%;\n height: 100%;\n }\n`;\n\n// Content Wrap\nexport const ContentWrap = styled.div`\n display: grid;\n box-sizing: border-box;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n overflow: auto;\n position: absolute;\n`;\nexport const AlertsWrap = styled(ContentWrap)`\n grid-template-columns: minmax(0,20rem) 1fr;\n`;\nexport const AnalysisWrap = styled(ContentWrap)`\n padding: .5rem;\n background: rgb(66,68,55);\n grid-template-rows: minmax(27rem, 1fr) minmax(27rem, 1fr);\n grid-gap: .5rem;\n\n /* Analysis sensors and map */\n & > section {\n display: grid;\n grid-gap: .5rem;\n grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));\n grid-auto-rows: minmax(16rem, 1fr);\n }\n`;\nexport const ProjectWrap = styled(ContentWrap)`\n // TODO: delete when done\n //grid-template-columns: minmax(0,20rem) 1fr; \n \n & .toggleFlightMenuButton {\n display: flex;\n background: rgba(0,0,0,.8);\n border: 1px solid rgba(255,255,255, .2);\n width: 2rem;\n height: 3rem;\n position: absolute;\n padding: .5rem;\n right: 0;\n margin-top: .5rem;\n align-items: center;\n cursor: pointer;\n z-index: 2;\n }\n`;\nexport const NotFoundWrap = styled(ContentWrap)`\n grid-template-rows: max-content 1fr;\n background: rgb(45,45,45) !important;\n\n & > .errCode {\n display: grid;\n justify-items: center;\n align-items: center;\n margin: 5% 25% 5%;\n font-size: 18vw;\n color: #fbfbfb;\n width: 50%;\n grid-template-columns: 1fr 1fr 1fr;\n user-select: none;\n\n & > img {\n border-radius: 50%;\n }\n }\n\n & > label {\n display: grid;\n position: relative;\n color: #fbfbfb;\n font-size: 3vh;\n align-items: top;\n margin: 0 10%;\n justify-items: center;\n line-height: 5vh;\n\n & > span > .link {\n font-size: 4vh;\n color: #fbfbfb;\n font-family: 'MontserratSemiBold'; \n\n &:hover {\n text-decoration: underline;\n color: rgb(0, 160, 255);\n }\n }\n }\n`;\n\n// Inputs\nexport const Input = styled.input`\n grid-column-start: 1;\n padding-left: 8px;\n border: 0;\n box-sizing: border-box;\n height: ${ props => props.height };\n background: ${ props => props.bg };\n grid-column-end: ${ props => props.colEnd };\n \n &::placeholder {\n font-size: .9rem;\n font-family: MontserratSemiBold;\n }\n &::-ms-input-placeholder {\n font-weight: bold;\n }\n`;\nexport const MenuInput = styled(Input)`\n height: 3rem;\n color: white;\n padding-right: 2rem;\n border: .08rem solid rgba(255,255,255,.8);\n border-radius: .1rem;\n background-color: transparent;\n background-size: 1.5rem;\n background-repeat: no-repeat;\n background-position: 97% 55%;\n\n &::placeholder {\n color: white;\n opacity: 1;\n }\n &::-ms-input-placeholder {\n color: white;\n }\n`;\nexport const Search = styled(MenuInput)`\n background-image: url(${searchIcon});\n`;\nexport const Write = styled(MenuInput)`\n background-image: url(${renameIcon});\n`;\n\n// Button\nexport const Button = styled.button`\n display: flex;\n position: relative;\n align-items: center;\n justify-content: space-around;\n padding: 0 .5rem;\n color: white;\n cursor: pointer;\n border: 0;\n font-family: MontserratSemiBold;\n width: ${ props => props.width };\n height: ${ props => props.height };\n justify-self: ${ props => props.justify };\n background: ${ props => props.theme.main };\n align-self: ${ props => props.align };\n font-size: .9rem;\n\n &:hover {\n filter: brightness(110%);\n }\n\n &:active {\n box-shadow: inset 0 0 .5rem .2rem rgb(0,0,0);\n }\n`;\nButton.defaultProps = {\n theme: {\n main: colors.mainRed \n }\n};\nexport const SecondaryButton = styled(Button)`\n display: flex;\n padding: 0 10px;\n font-size: .9rem;\n justify-content: start;\n background: transparent;\n border: .08rem solid rgba(255,255,255,.8);\n border-radius: .1rem;\n background-size: 1.7rem;\n background-repeat: no-repeat;\n background-position: 96% 45%;\n background-image: url(${ props => props.icon });\n`;\n\n// Error \nexport const Error = styled.div`\n padding: .5rem 1.5rem;\n box-sizing: border-box;\n color: ${ props => props.color ? props.color : 'white'};\n width: ${ props => props.width };\n height: ${ props => props.height };\n background: ${ props => \n props.warning ? props.theme.warning : props.theme.default };\n margin: ${ props => props.margin };\n`;\nError.defaultProps = {\n theme: {\n default: colors.mainRed,\n warning: colors.mainYellow\n }\n};\n\n// Unordered List\nexport const Ul = styled.ul`\n display: grid;\n grid-auto-rows: max-content;\n overflow: auto;\n margin: 0; \n padding: 0;\n width: ${ props => props.width };\n grid-gap: ${ props => props.gap };\n height: ${ props => props.height };\n max-height: ${ props => props.maxHeight };\n align-content: ${ props => props.alignContent};\n\n /* scrollbar */\n scrollbar-width: thin;\n scrollbar-color: rgb(100,100,100) transparent;\n\n &::-webkit-scrollbar {\n width: .3rem;\n }\n\n &::-webkit-scrollbar-thumb {\n background-color: rgb(100,100,100);\n }\n`;\n\nexport const Nav = styled(Ul)`\n z-index: 10;\n background: ${ colors.mainBlack };\n`;\n\n// List Items\nexport const Li = styled.li`\n display: grid;\n position: relative;\n cursor: pointer;\n color: white;\n background: ${ props => props.bg };\n`;\nexport const NavLi = styled(Li)`\n height: 4rem;\n justify-items: center;\n align-items: center;\n pointer-events: ${ props => props.pointerEvents };\n filter: brightness(${ props => props.brightness });\n\n &:hover {\n background: ${ colors.mainHover };\n }\n`;\nexport const GridLi = styled(Li)`\n grid-gap: .1rem;\n font-size: .8rem;\n padding: .5rem;\n margin-right: 5px;\n box-sizing: border-box;\n height: ${ props => props.height };\n background-color: ${ colors.mainBlack };\n display: ${ props => props.display };\n border-left: .2rem solid ${ props => \n props.selected ? \n colors.mainRed : 'transparent' \n };\n animation: ${expand} .5s ease-in-out;\n \n &>span:first-child {\n font-weight: bold;\n }\n\n & span {\n max-width: 85%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n & div:last-child {\n justify-self: center;\n }\n`;\n\n// Image\nexport const Img = styled.img`\n align-self: center;\n top: ${props => props.top ? props.top : 0};\n user-drag: none;\n user-select: none;\n cursor: ${ props => props.pointer ? 'pointer' : 'auto' };\n height: ${ props => props.height };\n right: ${ props => props.right };\n width: ${ props => props.width };\n position: ${ props => props.pos };\n --webkit-filter: ${ props => props.webkitFilter };\n object-fit: ${ props => props.objectFit };\n z-index: ${ props => props.zindex };\n`;\nexport const BgImg = styled(Img)`\n position: absolute;\n filter: blur(2rem);\n height: 100%;\n width: 100%;\n`;\n\n// Menu\nexport const Menu = styled.div`\n display: grid;\n margin-left: ${ props => props.hide ? '-20rem' : '0' };\n color: white;\n grid-gap: .5rem;\n width: 100%; \n max-width: 20rem;\n padding: .5rem;\n box-sizing: border-box;\n background: rgba(0,0,0,.5);\n right: ${ props => props.right };\n height: 100%;\n transition: margin 1s ease;\n`;\nexport const ProjectMenus = styled(Menu)`\n background: rgba(0,0,0,.9);\n box-shadow: inset 0 0 200rem rgba(150,150,150, .35);\n z-index: 2;\n\n @supports (backdrop-filter: blur(10px)) or \n (-webkit-backdrop-filter: blur(10px)) \n {\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n background: rgba(0,0,0,.5);\n box-shadow: none;\n }\n`;\nexport const NodeMenu = styled(ProjectMenus)`\n grid-template-rows: 4rem 1fr 2.5rem;\n min-height 100%;\n position: absolute;\n z-index: 3;\n\n &.reverse_slide_right{\n animation: ${reverse_slide_right} 1s forwards;\n }\n\n &.slide_right{\n animation: ${slide_right} 1s forwards;\n }\n & ul {\n padding-left: .5rem;\n \n & > li {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n }\n`;\nexport const FlightMenu = styled(ProjectMenus)`\n margin-left: auto;\n height: 100%;\n max-height: 27rem;\n width: 100%;\n max-width: 22em;\n overflow: hidden;\n grid-template-rows: 3rem max-content 3rem minmax(0, 1fr) 3rem;\n z-index: 1;\n position: relative;\n\n &.reverse_slide_up{\n animation: ${reverse_slide_up} 1s forwards;\n }\n\n &.slide_up{\n animation: ${slide_up} 1s forwards;\n }\n\n &>div:first-child {\n display: flex;\n overflow: hidden;\n justify-content: start;\n width: 90%;\n font-size: 2rem;\n padding-left: .5rem;\n align-items:center;\n font-family: MontserratSemiBold;\n\n & span {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n }\n & ul {\n grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));\n border-bottom: .1rem solid white;\n padding: .5rem; \n transition: height 1s ease;\n }\n`;\nexport const HomeMenu = styled(Menu)`\n min-height: 48rem;\n grid-template-rows: repeat(2, 3rem) 19rem 3rem minmax(0, 1fr) 2.5rem;\n`;\nexport const AlertsMenu = styled(Menu)`\n min-height: 100%;\n grid-template-rows: 3rem 2rem 3rem minmax(0,1fr) 2.5rem;\n grid-column: 1/2;\n grid-row: 1/2;\n z-index: 10;\n`;\n\n// Router Link\nexport const StyledLink = styled(Link)`\n display: flex;\n justify-content: center;\n align-items: center;\n position: absolute;\n height: 100%;\n width: 100%;\n color: white;\n text-decoration: none;\n`;\n\n// Checkbox\nexport const RowCheckbox = styled.label`\n display: flex;\n height: 3rem;\n justify-content: space-between;\n padding: 0 10px;\n align-items: center;\n border: .08rem solid rgba(255,255,255,.8);\n font-family: MontserratSemiBold;\n font-size: .9rem;\n cursor: pointer;\n user-select: none;\n\n & input {\n cursor: pointer;\n width: 1.5rem;\n height: 1.5rem;\n }\n`;\n\n// Alerts\nexport const LastSync = styled.span`\n user-select: none;\n font-size: .95rem;\n font-style: italic;\n text-align: end;\n border-bottom: .2rem solid white;\n margin: 0 -.5rem;\n padding: 0 .5rem;\n`;\n\nexport const AlertWindow = styled.div`\n display: grid;\n grid-template-rows: 3rem 1fr;\n visibility: ${ props => props.hide ? 'hidden' : 'visible' };\n color: white;\n height: 90%;\n width: 40rem;\n max-width: 100%;\n z-index: 20;\n margin: 2rem auto 0;\n background: rgba(0,0,0,.4);\n\n &>div:nth-child(2) {\n padding: 2rem;\n }\n\n @media (max-width: 960px) {\n box-shadow: 0 0 .3rem .3rem rgba(0,0,0,.95);\n grid-column: 1/3;\n grid-row: 1/2;\n\n &>div:first-child {\n background: rgb(0,0,0);\n }\n\n &>div:nth-child(2) {\n background: rgba(45,45,45,.98);\n }\n }\n`;\n\nexport const AlertHeader = styled.div`\n display: flex;\n padding: .5rem;\n justify-content: space-between;\n align-items: center;\n background: rgba(0,0,0,.4);\n\n &>span:first-child {\n font-weight: bold;\n }\n\n &>span:nth-child(2) {\n font-size: .9rem;\n }\n`;\n\n// Circle\nexport const Circle = styled.span`\n position: absolute;\n right: .2rem;\n top: .2rem;\n width: .5rem;\n height: .5rem;\n background: darkgrey;\n border-radius: 50%;\n`;\n\n// Chart\nexport const ChartStyle = styled.div`\n display: grid;\n grid-template-rows: minmax(4rem, max-content) minmax(4rem, 1fr);\n background: rgba(0,0,0,.4);\n margin-bottom: 1rem;\n position: relative;\n color: white;\n height: 100%;\n\n /* linechart header */\n &>div:first-child {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(0, 11rem));\n grid-auto-rows: 3rem;\n justify-content: end;\n grid-gap: .5rem;\n background: ${colors.mainBlack};\n padding: .5rem .5rem .5rem 5.5rem;\n box-sizing: border-box;\n\n &>span {\n position: absolute;\n left: 1rem;\n top: 1.5rem;\n font-family: MontserratSemiBold;\n }\n }\n`;\n\nexport const Sensors = styled.div`\n display: grid;\n grid-template-rows: 3rem 1fr;\n grid-gap: .5rem;\n color: white;\n overflow: hidden;\n\n /* HEADER */\n &>div:first-child {\n display: flex;\n box-sizing: border-box;\n justify-content: space-between;\n align-items: center;\n background: ${ colors.mainBlack };\n font-family: MontserratSemiBold;\n font-size: .9rem;\n padding: .4rem 1rem;\n }\n\n /* BODY */\n &>div:nth-child(2) {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); \n grid-auto-rows: max-content;\n overflow-y: auto;\n grid-gap: .5rem;\n padding-right: .4rem;\n\n /* SCROLLBAR */\n scrollbar-width: thin;\n scrollbar-color: rgb(100,100,100) transparent;\n\n &::-webkit-scrollbar {\n width: .3rem;\n }\n\n &::-webkit-scrollbar-thumb {\n background-color: rgb(100,100,100);\n }\n\n /* SENSOR */\n &>div {\n display: grid;\n grid-template-columns: 1fr 1fr;\n height: 6rem;\n background: rgba(20,20,20,1);\n box-sizing: border-box;\n padding: .4rem .4rem .4rem .6rem;\n align-items: center;\n position: relative;\n\n /* ALL TEXT */\n & span {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n }\n\n /* SENSOR NAME */\n & span:first-child {\n font-family: MontserratSemiBold;\n }\n\n /* SENSOR VALUES */\n &>div {\n display: flex;\n flex-direction: column;\n }\n\n /* AVG or RAW icon */\n & > img {\n position: absolute;\n width: 2rem;\n right: .2rem;\n top: -.1rem;\n }\n }\n }\n`;\n\nexport const Gauge = styled.div`\n display: block;\n width: 100%;\n max-width: ${ props => props.width };\n min-width: 8rem;\n align-self: flex-end;\n position: relative;\n\n /* unit */\n & > span {\n position: absolute;\n bottom: -.7rem;\n z-index: 1;\n left: 50%;\n transform: translateX(-50%);\n font-size: .8rem;\n color: grey;\n }\n \n /* gauge body */\n &>div {\n width: 100%;\n height: 0;\n padding-bottom: 50%;\n background: rgba(223,223,223);\n position: relative;\n border-top-left-radius: 100% 200%;\n border-top-right-radius: 100% 200%;\n overflow:hidden;\n\n /* gauge fill */\n &>div:first-child {\n position: absolute;\n top: 100%;\n width: inherit; \n height: 110%;\n background: ${ props => props.fill };\n transform-origin: center top;\n transform: rotate(${ props => props.turn }turn);\n transition: 0.5s ease-out;\n }\n\n /* label */\n &>div:nth-child(2) {\n background: rgb(20,20,20);\n position: absolute;\n width: 60%;\n height: 130%;\n border-radius: 50%;\n top: 40%;\n left: 50%;\n transform: translateX(-50%);\n\n /* text */\n display: flex;\n align-items: center;\n justify-content: center;\n padding-bottom: 20%;\n box-sizing: border-box;\n }\n }\n`;\n\nexport const MarkerButton = styled.div.attrs( props => ({\n tabIndex: '0'\n}))`\n background-color: ${ props => \n props.selected ? 'rgb(180, 50, 50)' : 'rgb(50, 50, 50)'};\n box-shadow: inset -.3rem -.2rem .5rem rgba(0,0,0,.9);\n border: 2px solid rgba(255,0,0,.5);\n border-radius: 50%;\n height: 2rem;\n width: 2rem;\n display: flex;\n justify-content: center;\n align-items: center;\n color: white;\n font-family: Montserrat;\n cursor: pointer;\n margin-left: -1rem;\n margin-top: -1rem;\n font-size: 1rem;\n`;\n\nexport const MaxIntensController =styled.div`\nwidth: 12rem;\nheight: 4rem;\nposition: fixed;\ntop: 0.5rem;\nleft: 30%;\n@media only screen and (max-width: 1366px) {\n left: 25%;\n}\n@media only screen and (max-width: 1024px) {\n left: 5rem;\n}\nbackground-color: rgb(20,20,20);\nborder-radius: .2rem;\ncolor: rgb(255, 255, 255);\ndisplay: flex; \njustify-content: space-between;\nflex-direction: column;\n& > form > div {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n & > span {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 30%;\n }\n}\n& Input {\n height: 2rem;\n width: 8rem;\n color: white;\n border-left: .08rem solid rgba(255,255,255,.8);\n border-radius: .1rem;\n background-color: transparent;\n &::placeholder {\n color: white;\n opacity: 1;\n }\n &::-ms-input-placeholder {\n color: white;\n }\n}\n& Button {\n width: 100%;\n height: 2rem;\n display: flex;\n padding: 0 10px;\n font-size: 17px;\n justify-content: center;\n background-color: #F9B513;\n border-radius: 0 0 .1rem .1rem;\n &:hover {\n background-color: rgba(150,150,150,.4);\n }\n}\n`\n","import React from 'react';\nimport ReactSelect from 'react-select';\nimport { colors } from './Styles';\n\nexport default function Select(props) {\n\n const styles = {\n control: (base,state) => ({\n ...base,\n background: props.black ? colors.mainBlack : 'transparent',\n borderRadius: '.1rem',\n margin: 0,\n height: '3rem',\n width: props.width,\n boxShadow: 0,\n borderColor: props.black ? colors.mainBlack : 'white',\n cursor: 'pointer',\n '&:hover': {\n borderColor: 'white'\n }\n }),\n singleValue: (base,state) => ({\n ...base,\n color: 'white'\n }),\n input: (base,state) => ({\n ...base,\n color: 'white'\n }),\n placeholder: (base,state) => ({\n ...base,\n color: 'white',\n fontFamily: 'MontserratSemiBold',\n fontSize: '.9rem'\n }),\n indicatorSeparator: (base) => ({\n display: 'none'\n }),\n menu: (base,state) => ({\n ...base,\n padding: 0,\n margin: 0,\n color: 'white',\n background: 'rgba(0,0,0,.96)',\n borderRadius: 0,\n zIndex: '2',\n boxShadow: 0\n }),\n menuList: (base) => ({\n ...base,\n padding: 0,\n margin: 0\n }),\n option: (base, state) => ({\n ...base,\n cursor: 'pointer',\n backgorundColor: 'transparent',\n '&:hover': {\n backgroundColor: 'rgba(255,255,255,.2)'\n },\n backgroundColor: state.isSelected\n ? 'rgba(0,0,0, .95)' : 'transparent',\n })\n };\n\n return(\n \n )\n}\n","import React from 'react';\r\nimport RDP, { DateUtils } from 'react-day-picker';\r\nimport chevronLeft from '../Assets/Icons/InnerBox_Left.svg';\r\nimport chevronRight from '../Assets/Icons/InnerBox_Right.svg';\r\nimport { colors } from './Styles';\r\nimport 'react-day-picker/lib/style.css';\r\n\r\nexport default function Calendar(props) {\r\n const from = props.date.from;\r\n const to = props.date.to;\r\n\r\n const clickHandler = (day) => {\r\n // set hours to 0:00 for better date comparison\r\n day.setHours(0);\r\n props.setDate(DateUtils.addDayToRange(day, props.date))\r\n } \r\n\r\n /*\r\n * FORMAT\r\n const modifiers = {\r\n flightDates: [\r\n {\r\n from: new Date(2020, 6, 2),\r\n to: new Date(2020, 6, 3)\r\n },\r\n {\r\n from: new Date(2020, 6, 7),\r\n to: new Date(2020, 6, 9)\r\n }\r\n ]\r\n };\r\n */\r\n\r\n /* to fix styles on lower res phones if needed use font-size: .9rem */\r\n const styles = `\r\n .DayPicker {\r\n width: 100%;\r\n box-sizing: border-box;\r\n }\r\n .DayPicker-wrapper {\r\n padding-bottom:0;\r\n }\r\n .DayPicker-Month {\r\n width: 100%;\r\n margin: 0;\r\n }\r\n .DayPicker-Caption {\r\n background: ${colors.mainBlack};\r\n padding: 1rem .5rem;\r\n color: white;\r\n }\r\n .DayPicker-NavButton {\r\n right: 0;\r\n top: .8rem;\r\n }\r\n .DayPicker-NavButton--prev {\r\n height: 1.5rem;\r\n width: 2rem;\r\n margin-right: 2.5rem;\r\n background-image: url(${chevronLeft});\r\n }\r\n .DayPicker-NavButton--next {\r\n height: 1.5rem;\r\n width: 2rem;\r\n background-image: url(${chevronRight});\r\n }\r\n .DayPicker-Body {\r\n color: white;\r\n }\r\n .DayPicker-Day {\r\n border-radius: 0;\r\n }\r\n .DayPicker:not(.DayPicker--interactionDisabled) \r\n .DayPicker-Day:not(\r\n .DayPicker-Day--disabled):not(\r\n .DayPicker-Day--selected):not(.DayPicker-Day--outside):hover {\r\n background-color: rgba(255,255,255,.1) !important;\r\n }\r\n .DayPicker-Day--selected:not(\r\n .DayPicker-Day--disabled):not(.DayPicker-Day--outside){\r\n background-color: ${colors.mainRed} !important;\r\n }\r\n .DayPicker-Day--flightDates {\r\n color: limegreen;\r\n font-weight: bold;\r\n }\r\n `;\r\n \r\n return(\r\n
\r\n \r\n \r\n
\r\n )\r\n}\r\n","import React from 'react';\r\n//import useSwr from 'swr';\r\n\r\nconst baseUrl = 'https://scentroid.dev';\r\n//const baseUrl = 'http://192.168.1.141:3000';\r\nexport const myHeaders = {\r\n Accept: 'application/json',\r\n 'Content-type': 'application/json'\r\n}\r\n\r\n// global and generic fetch for one time requests.\r\n// TODO: remove prod when backend is figured out\r\nexport const doFetch = async (method, path, signal, data) => {\r\n if (!path && !method) {\r\n throw new Error('Path and method are needed');\r\n }\r\n \r\n // add authorization \r\n if (localStorage.token) {\r\n myHeaders['Authorization'] = 'Bearer ' + localStorage.token;\r\n } \r\n\r\n // prepare parameters\r\n const url = baseUrl + path;\r\n const options = {\r\n method: method,\r\n body: JSON.stringify(data),\r\n credentials: 'include',\r\n headers: myHeaders\r\n }\r\n\r\n // adds signal to options\r\n if (signal) {\r\n options['signal'] = signal;\r\n }\r\n\r\n // make request\r\n const resp = await fetch(url,options);\r\n \r\n // handle errors\r\n if (resp.ok) {\r\n return resp.json();\r\n } else if (resp.status === 400) {\r\n // if status is 400 throw the text of the response built on backend\r\n const text = await resp.text();\r\n throw new Error(text);\r\n } else {\r\n // if any other error, just throw it and read statusText\r\n const err = new Error(resp.statusText);\r\n err.status = resp.status;\r\n throw err;\r\n }\r\n}\r\n\r\n// * generic get request for swr for continuous data pulling\r\n// TODO: remove prod when backend is figured out\r\n/*\r\nexport const useReq = (path, prod, options) => {\r\n if (!path) {\r\n throw new Error('Path is needed');\r\n }\r\n \r\n const url = prod ? prodUrl + path : baseUrl + path;\r\n const { data, error } = useSwr(url, options);\r\n\r\n if (error) {\r\n return 'req of ' + path + ' has ' + error;\r\n }\r\n\r\n return data;\r\n}\r\n\r\nexport const GetMapData = () => {\r\n const url = 'https://scentroid.dev/equipment/get_scentinals_map';\r\n const { data, error } = useSwr(url);\r\n\r\n if (error) {\r\n return { error };\r\n }\r\n\r\n if (!data) {\r\n return Loading...;\r\n }\r\n\r\n return data;\r\n}\r\n*/\r\n\r\n","/* dateFormat formats the date for last sync notification and for individual\r\n * list items with short and full formats respectively. */\r\nexport const dateParser = (timestamp, fullFormat, seconds) => {\r\n let date = new Date(timestamp);\r\n const month = ('0' + (date.getMonth()+1)).slice(-2);\r\n const day = ('0' + date.getDate()).slice(-2);\r\n\r\n let string = month + '.' + day + '.' + date.getFullYear();\r\n\r\n if (fullFormat) {\r\n const hours = ('0' + date.getHours()).slice(-2);\r\n const mins = ('0' + date.getMinutes()).slice(-2);\r\n\r\n if (seconds) {\r\n const seconds = ('0' + date.getSeconds()).slice(-2);\r\n return string + ' ' + hours + ':' + mins + ':' + seconds;\r\n }\r\n return string + ' ' + hours + ':' + mins;\r\n }\r\n\r\n return string;\r\n}\r\n","import React, { useState, useEffect } from 'react';\r\nimport favActive from '../Assets/Icons/Favourite_active.svg';\r\nimport Select from '../Containers/Select';\r\nimport Calendar from '../Containers/Calendar';\r\nimport { setFavourite, getProjects } from '../Containers/calls';\r\nimport { dateParser } from '../Containers/utility';\r\nimport { doFetch } from '../Containers/calls';\r\nimport { useAuth } from '../Containers/Context/auth';\r\nimport { \r\n Page, Img, ContentWrap, HomeMenu, Search, RowCheckbox, Ul, GridLi, \r\n Button, StyledLink, colors\r\n} from '../Containers/Styles';\r\n\r\nexport default function Home() { \r\n console.log('** Home rendered **');\r\n const { resetTokens } = useAuth();\r\n const [projects, setProjects] = useState([]);\r\n const [drones, setDrones] = useState([]);\r\n const [selectedProject, setSelectedProject] = useState(0);\r\n const [filter, setFilter] = useState({\r\n search: '',\r\n dropdown: undefined,\r\n date: {from: null, to: null},\r\n favourites: 0\r\n });\r\n\r\n useEffect(() => {\r\n doFetch('GET', '/equipment/list', 0)\r\n .then(drones => {\r\n console.log('drones req');\r\n setDrones(drones);\r\n })\r\n .catch(err => {\r\n console.log(err)\r\n if (err.status === 401) {\r\n resetTokens();\r\n }\r\n });\r\n },[]);\r\n\r\n // send request everytime parameters are updated with 2s delay, if values are\r\n // default, clear timeout\r\n useEffect(() => {\r\n console.log('filter render', filter);\r\n const timeout = setTimeout(() => {\r\n let url = '/project/search?';\r\n if (filter.search !== '') {\r\n url += `name=${filter.search}&`;\r\n console.log('url update with name has worked');\r\n }\r\n if (filter.dropdown !== undefined) {\r\n url += `equipment_hash_id=${filter.dropdown}&`;\r\n console.log('url update with dropdown has worked');\r\n }\r\n if (filter.favourites) {\r\n url += `is_favourite=true&`;\r\n console.log('url update with favs has worked');\r\n }\r\n if (filter.date.from) {\r\n console.log(Math.floor(filter.date.from.getTime() / 1000) + 60*60*24);\r\n url += `start_timestamp=${\r\n Math.floor(filter.date.from.getTime() / 1000)}&`;\r\n\r\n if (!filter.date.to || +filter.date.from === +filter.date.to) {\r\n url += `end_timestamp=${Math.floor(filter.date.from.getTime() / 1000) + 60*60*24}&`;\r\n } else {\r\n url += `end_timestamp=${\r\n Math.floor(filter.date.to.getTime() / 1000)}&`;\r\n }\r\n console.log('url update with dates has worked');\r\n }\r\n\r\n doFetch('GET', url, 0)\r\n .then(projects => {\r\n console.log(projects);\r\n setProjects(projects);\r\n })\r\n .catch(err => {\r\n console.log(err)\r\n if (err.status === 401) {\r\n resetTokens();\r\n }\r\n });\r\n },500);\r\n \r\n return () => clearTimeout(timeout)\r\n },[filter]);\r\n \r\n /* filterMethod filters the list of projects by user inputs in Search, \r\n Dropdown, Calendar and Favourites inputs. \r\n const filterMethod = (key) => {\r\n const f = filter.favourites && !projects[key].project_favourite;\r\n const date = !checkDate(key);\r\n const d = filter.dropdown &&\r\n projects[key].drone_name !== filter.dropdown;\r\n const s = filter.search && \r\n !projects[key].project_name.toLowerCase().includes(filter.search);\r\n\r\n if (f || date || d || s) {\r\n // reset filtered out, selected project\r\n if (+key === +selectedProject) { \r\n setSelectedProject(0);\r\n }\r\n return 0;\r\n }\r\n return key;\r\n }\r\n\r\n /*\r\n /* checkDate checks if projects flight dates occured on calendar's selected\r\n date, or within selected date range. \r\n const checkDate = (key) => {\r\n const flights = projects[key].flights, fd = filter.date;\r\n\r\n // If 'to' is defined, and 'from' doesn't equal 'to' range is selected.\r\n if (fd.to && !datesAreOnSameDay(fd.from, fd.to)) {\r\n for (let i in flights) {\r\n const flightFrom = new Date(flights[i].from), \r\n flightTo = new Date(flights[i].to);\r\n\r\n // If any flight date fits within the selected range, return 1;\r\n if ((flightFrom >= fd.from && flightFrom <= fd.to)\r\n || (flightTo >= fd.from && flightTo <= fd.to)) {\r\n console.log(\r\n '!FLIGHT! ' + projects[key].project_name, \r\n flightFrom, \r\n flightTo, \r\n '!fd range!', \r\n fd.from, \r\n fd.to);\r\n return 1;\r\n }\r\n }\r\n return 0;\r\n }\r\n /* Otherwise, if 'to' is null, OR 'to' and 'from' and equal, we check if \r\n 'from' is defined. If it is, then it's safe to use 'from' only. \r\n else if (fd.from) {\r\n for (let i in flights) {\r\n const flightFrom = new Date(flights[i].from),\r\n flightTo = new Date(flights[i].to);\r\n\r\n /* If any flight in the project happened on that day OR if flight range\r\n * has filter date in between start and end date, return 1. \r\n if (datesAreOnSameDay(flightFrom, fd.from) \r\n || datesAreOnSameDay(flightTo, fd.from)\r\n || (fd.from > flightFrom && fd.from < flightTo)) {\r\n console.log(\r\n '!FLIGHT! ' + projects[key].project_name, \r\n flightFrom, \r\n flightTo, \r\n '!fd from!', \r\n fd.from);\r\n return 1;\r\n }\r\n }\r\n return 0;\r\n }\r\n else {\r\n return 1;\r\n } \r\n }\r\n\r\n const datesAreOnSameDay = (first, second) => (\r\n first.getFullYear() === second.getFullYear() &&\r\n first.getMonth() === second.getMonth() &&\r\n first.getDate() === second.getDate() \r\n )\r\n */\r\n\r\n // makes request to the server to set the project to favourite state, and\r\n // asyncronously updates the star of the project.\r\n const favClickHandler = (i, id) => {\r\n doFetch('POST', `/project/${id}/favourite`, 0)\r\n .then(json => {\r\n console.log('fav updated');\r\n })\r\n .catch(err => {\r\n console.log(err)\r\n if (err.status === 401) {\r\n resetTokens();\r\n }\r\n });\r\n }\r\n\r\nreturn(\r\n \r\n \r\n \r\n setFilter({\r\n ...filter, \r\n search: event.target.value.trim().toLowerCase()\r\n })}/> \r\n {\r\n setFilter({...filter, favourites: +event.target.checked});\r\n }}/>\r\n \r\n
    \r\n {\r\n projects\r\n .map((prj, i) => {\r\n return (\r\n setSelectedProject(prj.id)}\r\n selected={selectedProject === prj.id}>\r\n Project: {prj.name}\r\n {\r\n e.stopPropagation();\r\n // make request to change the favourite\r\n favClickHandler(i, prj.id);\r\n // flip the boolean of favourite project\r\n prj.is_favourite = !prj.is_favourite;\r\n // assign the flipped style to the star\r\n e.target.style.filter = !prj.is_favourite ? \r\n 'grayscale(1) brightness(50%)' : null;\r\n }}/>\r\n Flights: {prj.travel_sessions.length}\r\n Length: {Math.floor(prj.time_length / 60)\r\n } minutes {prj.time_length % 60} seconds\r\n {\r\n prj.end_timestamp ? \r\n
    \r\n \r\n {dateParser(prj.start_timestamp * 1000, 0) + \r\n ' - ' + \r\n dateParser(prj.end_timestamp * 1000, 0)}\r\n \r\n
    \r\n :
    -
    \r\n }\r\n
    \r\n )\r\n })\r\n }\r\n
\r\n \r\n
\r\n
\r\n
\r\n );\r\n}\r\n\r\n","import React, { useState, useEffect, useCallback } from 'react';\nimport { Steps } from 'intro.js-react';\nimport { NavLi, Img } from './Styles';\nimport guideIcon from '../Assets/Icons/Help.svg';\nimport 'intro.js/introjs.css';\nimport 'intro.js/themes/introjs-modern.css';\nimport drimsGuide from '../Assets/drimsGuide.json';\n\n// props: location \nexport default function Guide(props) {\n const [guideState, setGuideState] = useState(false);\n // grabs the first word with first forward slash of the location\n const currentPage = props.location.match(/^\\/\\w*/g)[0];\n const flightId = localStorage.getItem('flightId') || null;\n const [stepHook, setStepHook] = useState(null);\n\n // depending on the location returns appropriate steps\n const getSteps = () => {\n\n return drimsGuide[currentPage];\n /*\n */\n }\n\n // before change method for introjs, triggers specific events according to\n // the active page and step.\n const beforeClick = (nextStepIndex) => {\n if (currentPage === '/project') { \n // force user to select the flight to see the change\n if (nextStepIndex === 3 && !localStorage.getItem('flightId')) {\n return false;\n }\n\n const mapControls = document.querySelector('.mapControls');\n if (nextStepIndex === 6 && mapControls) {\n const marker = document.querySelector('.mapMarker');\n if (marker) {\n marker.click();\n mapControls.children[0].click();\n }\n }\n if (nextStepIndex === 8 && mapControls) {\n mapControls.children[1].click();\n }\n if (nextStepIndex === 9 && mapControls) {\n mapControls.children[2].click();\n }\n } else if (currentPage === '/analysis') { \n // force user to select the flight to see the change\n if (nextStepIndex === 2 && !localStorage.getItem('flightId')) {\n return false;\n }\n \n const marker = document.querySelector('.mapMarker');\n if (nextStepIndex === 4 && marker) {\n marker.click();\n }\n } else if (currentPage === '/alerts') {\n const alerts = document.querySelector('.alertsMenu').children;\n if (nextStepIndex === 3 && alerts.length) {\n alerts[0].click(); \n }\n }\n }\n\n const onExit = () => {\n setGuideState(false);\n }\n\n //options={{disableInteraction: true}}\n return(\n setGuideState(true)} title='Guide'> \n navIcon/guide\n setStepHook(step)}\n enabled={guideState}\n steps={getSteps()}\n onBeforeChange={beforeClick}\n initialStep={0}\n onExit={onExit}\n />\n \n ); \n}\n\n","import React from 'react';\r\nimport { useLocation } from 'react-router-dom';\r\nimport MenuIcon from '../Assets/Icons/Calendar.svg';\r\nimport ProjectIcon from '../Assets/Icons/Map_main.svg';\r\nimport AnalysisIcon from '../Assets/Icons/Analysis.svg';\r\n//import AlertsIcon from '../Assets/Icons/Mail.svg';\r\n//import ActiveAlertsIcon from '../Assets/Icons/Mail_Notification.svg';\r\nimport LogoutIcon from '../Assets/Icons/Logout.svg';\r\nimport Guide from './Guide';\r\nimport { StyledLink, colors, Img, NavLi, Nav, GuideStyle } from './Styles';\r\n\r\n// props: newAlerts, logOut\r\nexport default function Navbar(props) {\r\n const projectId = localStorage.getItem('projectId') || 0;\r\n\r\n // get the current path\r\n const location = useLocation().pathname;\r\n const listItems = [\r\n { \r\n icon: MenuIcon, \r\n link: '/', \r\n status: 1,\r\n name: 'Home'\r\n },\r\n { \r\n icon: ProjectIcon, \r\n link: `/project/${projectId}`, \r\n status: projectId,\r\n name: 'Project'\r\n },\r\n { \r\n icon: AnalysisIcon, \r\n link: `/analysis/${projectId}`, \r\n status: projectId,\r\n name: 'Analysis'\r\n },\r\n /*\r\n {\r\n icon: (props.newAlerts ? ActiveAlertsIcon : AlertsIcon),\r\n link: '/alerts', \r\n status: 1,\r\n name: 'Alerts'\r\n },\r\n */\r\n ];\r\n\r\n // map function\r\n const listItemsMap = (item, i) => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n )\r\n }\r\n\r\n return (\r\n \r\n );\r\n}\r\n","import React, { useState, useRef, useCallback, useEffect } from 'react';\nimport GoogleMapReact from 'google-map-react';\nimport { useForm } from 'react-hook-form';\nimport { yupResolver } from '@hookform/resolvers/yup';\nimport * as Yup from 'yup';\nimport { MarkerButton, colors, MaxIntensController, Input, Button } from './Styles';\nimport defaultMapIcon from '../Assets/Icons/Map_main.svg';\nimport map3dIcon from '../Assets/Icons/3DMapping.svg';\nimport heatmapIcon from '../Assets/Icons/Heatmap.svg';\nimport pathIcon from '../Assets/Icons/pathIcon.svg';\nimport useSupercluster from 'use-supercluster';\nimport '../index.css';\n\n// props: flight, setNodeInfo, mapControls, selectedCoords\nexport default function GoogleMap(props) {\n const mapRef = useRef();\n const mapsRef = useRef();\n const [zoom, setZoom] = useState(3);\n const [bounds, setBounds] = useState({\n ne: { lat: 63, lng: 180 },\n nw: { lat: 63, lng: -146.25 },\n se: { lat: -63, lng: 180 },\n sw: { lat: -63, lng: -146.25 }\n });\n const [mapType, setMapType] = useState('satellite');\n // active control is made to decide what control is on. 0 - default,\n // 1 - heatmap, 2 - flightpath, 3 - 3d map\n const [activeControl, setActiveControl] = useState(0);\n const [flightPath, setFlightPath] = useState(null);\n const [mapPoints, setPoints] = useState([]);\n const [heatmapData, setHeatmapData] = useState([]);\n const [heatmapInstance, setHeatmapInstance] = useState('');\n const [customMax, setCustomMax] = useState(0);\n const [heatmapSensor, setHeatmapSensor] = useState({\n id: null,\n limit: null\n });\n const validationSchema = Yup.object().shape({\n max: Yup.number()\n .required('The number is required!')\n .min(0)\n .typeError('value must be number')\n // .oneOf(['Yes'], 'Unable to delete before confirmation'),\n });\n const formOptions = {\n mode: 'all',\n resolver: yupResolver(validationSchema),\n };\n const { register, handleSubmit, reset, formState: { errors } } = useForm(formOptions);\n const onSubmit = (data) => {\n if (data.max >= 0) {\n setCustomMax(data.max);\n heatmapInstance.setOptions({\n data: heatmapData,\n maxIntensity: data.max\n })\n } else {\n alert('Maximum value should not be negative')\n }\n }\n // ** EFFECT METHODS **\n // 1. Updates map whenever flight changes\n useEffect(() => {\n /*remove previous heatmap instance when changing flight \n since map will create a new heatmap instance\n */\n if (heatmapInstance) {\n heatmapInstance.setMap(null);\n setHeatmapInstance('');\n reset();\n }\n if (props.flight.samples && props.flight.samples.length) {\n // 1.1 Build points for marker/cluster format, and add alt to values for\n // avg calculation\n const points = props.flight?.samples.map(node => ({\n type: 'Feature',\n properties: {\n cluster: false,\n nodeId: node.timestamp,\n value: {\n ...node.values, alt: {\n value: node.altitude,\n sensor_name: 'Altitude'\n }\n }\n },\n geometry: { type: 'Point', coordinates: [node.longitude, node.latitude] }\n }));\n\n // 1.2 set points for clusters\n setPoints(points);\n\n // 1.3 When points are built - ...\n if (mapRef.current && points.length) {\n // 1.3.1 reset the control to default map view\n setActiveControl(0);\n\n // 1.3.2 fit bounds to a new flight \n const initPoint = {\n lat: points[0].geometry.coordinates[1],\n lng: points[0].geometry.coordinates[0]\n };\n const flightBounds = new mapsRef.current.LatLngBounds();\n\n for (let i in points) {\n flightBounds.extend({\n lat: points[i].geometry.coordinates[1],\n lng: points[i].geometry.coordinates[0]\n });\n }\n mapRef.current.fitBounds(flightBounds);\n\n // 1.3.3 create flightpath with polylines \n const path = points.map(p => ({\n 'lat': p.geometry.coordinates[1],\n 'lng': p.geometry.coordinates[0]\n }));\n\n // 1.3.4 Reset previous flightpath if it was already created\n if (flightPath) {\n flightPath.setMap(null);\n }\n // 1.3.5 Set new flight path\n setFlightPath(new mapsRef.current.Polyline({\n path: path,\n geodesic: 1,\n strokeColor: '#ffc403',\n strokeOpacity: 1,\n strokeWeight: 2\n }));\n }\n\n // 1.3.6 Set heatmap sensor, if no aq_limit is set, set it yourself\n let aq_limit = props.flight.sensors[0].aq_limit;\n if (!aq_limit) {\n aq_limit = Math.max.apply(Math,\n props.flight.samples.map(function (o) {\n return o.values[props.flight.sensors[0].id].value;\n }\n ));\n }\n\n // 1.3.7 add heatmap sensors for heatmap dropdown \n if (props.mapControls && props.flight.samples.length &&\n mapRef.current) {\n const controlsWrap = mapRef.current.controls\n [mapsRef.current.ControlPosition.TOP_CENTER];\n let controls = null;\n for (let i in controlsWrap) {\n if (controlsWrap[i] &&\n controlsWrap[i][0] &&\n controlsWrap[i][0].className === 'mapControls') {\n controls = controlsWrap[i][0];\n break;\n }\n }\n\n // clear prev dropdown\n if (controls.children.length > 3) {\n controls.removeChild(controls.children[3]);\n }\n\n // reset heatmapSensor\n setHeatmapSensor({\n id: null,\n limit: null\n });\n\n // create new one\n const dropdown = document.createElement('select');\n dropdown.style.backgroundColor = colors.mainBlack;\n dropdown.style.gridColumn = '1/4';\n dropdown.style.color = '#fff';\n dropdown.style.fontSize = '1rem';\n dropdown.style.border = 0;\n dropdown.style.height = '0';\n dropdown.style.cursor = 'pointer';\n dropdown.style.transition = 'height .5s ease';\n dropdown.classList.add('heatDropdown');\n\n // add placeholder\n const option = document.createElement('option');\n option.innerText = 'Select sensor';\n option.value = '';\n option.disabled = 1;\n option.hidden = 1;\n option.selected = 1;\n dropdown.appendChild(option);\n\n // add event\n dropdown.addEventListener('change', function (e) {\n for (let i in props.flight.sensors) {\n if (e.target.value === props.flight.sensors[i].id) {\n setHeatmapSensor({\n id: e.target.value,\n limit: props.flight.sensors[i].aq_limit * 1.2\n });\n break;\n }\n }\n });\n\n // fill up dropdown\n for (let i in props.flight.sensors) {\n const sensor = props.flight.sensors[i];\n const option = document.createElement('option');\n option.innerText = sensor.name;\n option.value = sensor.id;\n dropdown.appendChild(option);\n }\n\n controls.appendChild(dropdown);\n }\n // create heatmap layer without data when flight is chosen. Update data when sensor is selected after\n if (mapsRef.current) {\n const heatmapInst = new mapsRef.current.visualization.HeatmapLayer({\n data: [],\n dissipating: 0,\n radius: 0.00004,\n opacity: 1,\n // maxIntensity: heatmapSensor?.limit\n maxIntensity: 0\n });\n setHeatmapInstance(heatmapInst);\n }\n }\n }, [props.flight]);\n\n // remove current heatmap when switch with mapControls\n useEffect(() => {\n if (heatmapInstance !== '')\n heatmapInstance.setOptions({\n data: [],\n })\n reset();\n }, [activeControl]);\n\n // 2. update heatmap when heatmapsensor is updated \n useEffect(() => {\n console.log('heatmap effect render');\n reset();\n if (props.flight.samples && props.flight.samples.length &&\n props.mapControls) {\n // 2. ** Build heatmap data and calculate saturation and weight **\n let initHeatPositions = props.flight.samples.map(node => ({\n lat: node.latitude,\n lng: node.longitude,\n weight: heatmapSensor.id ? node.values[heatmapSensor.id].value : 0\n }));\n // 2.1 2d loop creates a 2d array with all the indexes of all points \n // that have nested array that provides indexes of points that are \n // located close to the parent.\n // const step = 0.000009;\n const step = 0.00005;\n let uniquePositions = [];\n for (let i = 0; i < initHeatPositions.length; ++i) {\n var closePoints = [];\n for (let j = i + 1; j < initHeatPositions.length; ++j) {\n const lngDiff = initHeatPositions[i].lng - initHeatPositions[j].lng;\n const latDiff = initHeatPositions[j].lat - initHeatPositions[i].lat;\n const distance = Math.sqrt(Math.pow(lngDiff, 2) + Math.pow(latDiff, 2));\n if (distance < step) {\n closePoints.push(j);\n }\n }\n uniquePositions.push(closePoints);\n }\n // 2.2 Then 2d array have to be filtered for unique points, to remove \n // repetitions of nested children of close located points.\n for (let i = 0; i < uniquePositions.length; ++i) {\n const pos = uniquePositions[i];\n // if position has not been deleted due nesting \n if (pos) {\n for (let j = 0; j < pos.length; ++j) {\n const unique = pos[j];\n\n // Delete repeating position either in nested children or in its own\n // index\n if (uniquePositions[unique]) {\n uniquePositions[unique] = null;\n } else {\n pos.splice([pos.indexOf(unique)], 1);\n --j;\n }\n }\n }\n }\n // 2.3 Finally it builds an array of heatPoints using unique indexes for\n // previous step\n const heatPositions = [];\n for (let i = 0; i < uniquePositions.length; ++i) {\n // if current unique position is not 'null'\n if (uniquePositions[i]) {\n // if it's a cluster\n if (uniquePositions[i].length) {\n const pos = {\n lat: initHeatPositions[i].lat,\n lng: initHeatPositions[i].lng,\n weight: initHeatPositions[i].weight\n };\n for (let j in uniquePositions[i]) {\n pos.lat += initHeatPositions[uniquePositions[i][j]].lat;\n pos.lng += initHeatPositions[uniquePositions[i][j]].lng;\n pos.weight += initHeatPositions[uniquePositions[i][j]].weight;\n }\n pos.lat /= (uniquePositions[i].length + 1);\n pos.lng /= (uniquePositions[i].length + 1);\n pos.weight /= (uniquePositions[i].length + 1);\n\n const heatmapPoint = {\n location: new mapsRef.current.LatLng(pos.lat, pos.lng),\n weight: pos.weight,\n }\n\n // heatPositions.push(pos);\n heatPositions.push(heatmapPoint);\n } else { // else it's 1 point\n const heatmapPoint = {\n location: new mapsRef.current.LatLng(initHeatPositions[i].lat, initHeatPositions[i].lng),\n weight: initHeatPositions[i].weight,\n }\n // heatPositions.push(initHeatPositions[i]);\n heatPositions.push(heatmapPoint);\n }\n }\n }\n // clear temporary data used for calculation\n initHeatPositions = null;\n uniquePositions = null;\n setHeatmapData(heatPositions);\n // Once new sensor selected, heatmap will not show until max value and \"plot\" btn clicked\n activeControl === 1 && heatmapInstance.setMap(mapRef.current);\n heatmapInstance.setOptions({\n data: [],\n })\n\n // TBD: testing method for heatmap unique point consistency\n /*\n let last = uniquePositions.length-1;\n for (let i = 0; i < uniquePositions.length; ++i) {\n const pos = uniquePositions[i];\n if (pos) {\n for (let j = 0; j < pos.length; ++j) {\n if (pos[j] === last) {\n console.log(i + ' is unique cluster with last point');\n last = null;\n }\n }\n }\n }\n if (last) {\n console.log('last point is unique, no issues');\n }\n */\n }\n }, [heatmapSensor]);\n\n // update map according to its control\n useEffect(() => {\n if (mapRef.current && flightPath) {\n // reset map values (remove flight path, reset tilt and set all map\n // controls to black color);\n flightPath.setMap(null);\n mapRef.current.setTilt(0);\n document.querySelector('.heatDropdown').style.height = '0';\n [...document.querySelector('.mapControls').children]\n .map(btn => btn.style.backgroundColor = colors.mainBlack);\n\n // sets update active control to a red color\n [...document.querySelector('.mapControls').children][activeControl]\n .style.backgroundColor = colors.mainRed;\n\n if (activeControl === 3) {\n mapRef.current.setTilt(45);\n } else if (activeControl === 2) {\n flightPath.setMap(mapRef.current);\n props.setNodeInfo(null);\n } else if (activeControl === 1) {\n document.querySelector('.heatDropdown').style.height = '2rem';\n props.setNodeInfo(null);\n }\n }\n }, [activeControl]);\n // ** EO EFFECT METHODS **\n\n /*\n * Check the amount of sensors in map points to match\n console.log('FLIGHT', props.flight.id);\n for ( let i in mapPoints ) {\n // TODO: define length to check with \n const checkLength = 9;\n const iterate_length = Object.keys(mapPoints[i].properties.value).length;\n if (checkLength !== iterate_length) {\n console.log(iterate_length, mapPoints[i].properties.nodeId);\n }\n }\n */\n\n // useSuperCluster method - creates clusters on the map \n const { clusters, supercluster } = useSupercluster({\n points: mapPoints,\n bounds,\n zoom,\n options: { radius: 75, maxZoom: 20 }\n });\n\n // ** UTILITY METHODS **\n // Options method setup with callback hook. Callback hook was \n // implemented to prevent the map from flickering since the only time we \n // need it to reload would be when the type has changed.\n const createOptions = useCallback((maps) => ({\n restriction: {\n latLngBounds: {\n north: 85,\n south: -85,\n west: -179,\n east: 180\n }\n },\n styles: [\n { elementType: 'geometry', stylers: [{ color: '#242f3e' }] },\n { elementType: 'labels.text.stroke', stylers: [{ color: '#242f3e' }] },\n { elementType: 'labels.text.fill', stylers: [{ color: '#746855' }] },\n {\n featureType: 'administrative.locality',\n elementType: 'labels.text.fill',\n stylers: [{ color: '#d59563' }]\n },\n {\n featureType: 'poi',\n elementType: 'labels.text.fill',\n stylers: [{ color: '#d59563' }]\n },\n {\n featureType: 'poi.park',\n elementType: 'geometry',\n stylers: [{ color: '#263c3f' }]\n },\n {\n featureType: 'poi.park',\n elementType: 'labels.text.fill',\n stylers: [{ color: '#6b9a76' }]\n },\n {\n featureType: 'road',\n elementType: 'geometry',\n stylers: [{ color: '#38414e' }]\n },\n {\n featureType: 'road',\n elementType: 'geometry.stroke',\n stylers: [{ color: '#212a37' }]\n },\n {\n featureType: 'road',\n elementType: 'labels.text.fill',\n stylers: [{ color: '#9ca5b3' }]\n },\n {\n featureType: 'road.highway',\n elementType: 'geometry',\n stylers: [{ color: '#746855' }]\n },\n {\n featureType: 'road.highway',\n elementType: 'geometry.stroke',\n stylers: [{ color: '#1f2835' }]\n },\n {\n featureType: 'road.highway',\n elementType: 'labels.text.fill',\n stylers: [{ color: '#f3d19c' }]\n },\n {\n featureType: 'transit',\n elementType: 'geometry',\n stylers: [{ color: '#2f3948' }]\n },\n {\n featureType: 'transit.station',\n elementType: 'labels.text.fill',\n stylers: [{ color: '#d59563' }]\n },\n {\n featureType: 'water',\n elementType: 'geometry',\n stylers: [{ color: '#17263c' }]\n },\n {\n featureType: 'water',\n elementType: 'labels.text.fill',\n stylers: [{ color: '#515c6d' }]\n },\n {\n featureType: 'water',\n elementType: 'labels.text.stroke',\n stylers: [{ color: '#17263c' }]\n },\n {\n featureType: \"administrative\",\n elementType: \"geometry\",\n stylers: [{ visibility: \"off\" }]\n },\n {\n featureType: \"poi\",\n stylers: [{ visibility: \"off\" }]\n },\n {\n featureType: \"road\",\n elementType: \"labels.icon\",\n stylers: [{ visibility: \"off\" }]\n },\n {\n featureType: \"transit\",\n stylers: [{ visibility: \"off\" }]\n }\n ],\n mapTypeControl: true,\n rotateControl: false,\n mapTypeControlOptions: {\n position: maps.ControlPosition.BOTTOM_CENTER,\n mapTypeIds: [maps.MapTypeId.SATELLITE, maps.MapTypeId.ROADMAP]\n },\n mapTypeId: mapType,\n fullscreenControlOptions: {\n position: maps.ControlPosition.BOTTOM_RIGHT\n },\n /*\n Rewrites default library settings of minZoom.\n Values less than 4 might cause the marker calculation problem,\n therefore try to switch it around if that's the case.\n */\n minZoom: 3,\n backgroundColor: 'none'\n }), [mapType]);\n\n // update info of the node in the box, if the different node was selected\n const markerOnClick = (info) => {\n if (!compareCoords(info.coords)) {\n props.setNodeInfo(info);\n }\n }\n\n // checks if coordinates array is equal. Supposed to take [lng, lat] array\n // as each value for comparison\n const compareCoords = (nodeCoords) => {\n return (\n props.selectedCoords &&\n props.selectedCoords[0] === nodeCoords[0] &&\n props.selectedCoords[1] === nodeCoords[1]\n );\n }\n\n // creates the custom map controls for default view, heatmap and 3d view.\n const createMapControls = (controlDiv: Element, map: google.maps.Map, flight) => {\n // add class to controlDiv\n controlDiv.classList.add('mapControls');\n\n // all button settings\n const defaultMapBtn = document.createElement('div');\n const heatMapBtn = document.createElement('div');\n const map3dBtn = document.createElement('div');\n const flightPathBtn = document.createElement('div');\n\n // default map is selected by default\n defaultMapBtn.style.backgroundColor = colors.mainRed;\n defaultMapBtn.style.display = 'flex';\n heatMapBtn.style.display = 'flex';\n map3dBtn.style.display = 'flex';\n flightPathBtn.style.display = 'flex';\n defaultMapBtn.style.justifyContent = 'center';\n heatMapBtn.style.justifyContent = 'center';\n map3dBtn.style.justifyContent = 'center';\n flightPathBtn.style.justifyContent = 'center';\n\n // set index of active control to state\n controlDiv.addEventListener('click', function (e) {\n const index = [...controlDiv.children].indexOf(e.target);\n if (index > -1 && index < 3) {\n setActiveControl(index);\n }\n });\n\n // all icon settings\n const defImg = document.createElement('img');\n const heatImg = document.createElement('img');\n const d3Img = document.createElement('img');\n const pathImg = document.createElement('img');\n\n defImg.setAttribute('src', defaultMapIcon);\n heatImg.setAttribute('src', heatmapIcon);\n d3Img.setAttribute('src', map3dIcon);\n pathImg.setAttribute('src', pathIcon);\n defImg.style.pointerEvents = 'none';\n heatImg.style.pointerEvents = 'none';\n d3Img.style.pointerEvents = 'none';\n pathImg.style.pointerEvents = 'none';\n defImg.style.width = '2rem';\n heatImg.style.width = '2rem';\n d3Img.style.width = '2rem';\n pathImg.style.width = '2rem';\n\n // append icons to buttons\n defaultMapBtn.appendChild(defImg);\n heatMapBtn.appendChild(heatImg);\n map3dBtn.appendChild(d3Img);\n flightPathBtn.appendChild(pathImg);\n\n // control wrap settings\n controlDiv.style.gridTemplateColumns = '4rem 4rem 4rem';\n controlDiv.style.gridTemplateRows = '4rem 1fr';\n controlDiv.style.backgroundColor = 'rgb(20,20,20)';\n controlDiv.style.cursor = 'pointer';\n controlDiv.style.marginTop = '.5rem';\n controlDiv.style.display = 'grid';\n\n // append all buttons to control div\n controlDiv.appendChild(defaultMapBtn);\n controlDiv.appendChild(heatMapBtn);\n controlDiv.appendChild(flightPathBtn);\n //controlDiv.appendChild(map3dBtn);\n }\n return (\n <>\n {\n mapRef.current = map;\n mapsRef.current = maps;\n\n // 1.3.7 add map controls on the top with new dropdown\n if (props.mapControls) {\n const controlDiv = document.createElement('div');\n createMapControls(controlDiv, mapRef.current, props.flight);\n\n mapRef.current.controls[mapsRef.current.ControlPosition.TOP_CENTER]\n .push(controlDiv);\n }\n }}\n onClick={() => { props.setNodeInfo() }}\n onChange={({ zoom, bounds }) => {\n setZoom(zoom);\n setBounds([\n bounds.nw.lng,\n bounds.se.lat,\n bounds.se.lng,\n bounds.nw.lat\n ]);\n }}\n onMapTypeIdChange={(id) => { setMapType(id) }}\n >\n {activeControl !== 1 && activeControl !== 2 ?\n clusters.map(cluster => {\n const [lng, lat] = cluster.geometry.coordinates;\n const {\n cluster: isCluster,\n point_count: pointCount\n } = cluster.properties;\n\n if (isCluster) {\n return (\n {\n e.stopPropagation();\n\n const leaves = supercluster.getLeaves(cluster.id, Infinity);\n\n // store the first index of leaves as initial value for avg\n // calc\n const avg = JSON.parse(\n JSON.stringify(leaves[0].properties.value));\n const min = JSON.parse(\n JSON.stringify(leaves[0].properties.value));\n const max = JSON.parse(\n JSON.stringify(leaves[0].properties.value));\n\n // loop through points \n for (let i = 1, l = leaves.length; i < l; ++i) {\n // per sensor in point\n for (let j in leaves[i].properties.value) {\n const sensor = leaves[i].properties.value[j];\n avg[j].value += sensor.value;\n\n // get mins\n if (min[j].value > sensor.value) {\n min[j].value = sensor.value;\n }\n\n // get maxes\n if (max[j].value < sensor.value) {\n max[j].value = sensor.value;\n }\n }\n }\n\n // calc avg\n for (let i in avg) {\n avg[i].value /= leaves.length;\n }\n\n markerOnClick({\n id: cluster.id,\n coords: [lng, lat],\n data: leaves,\n avgTemp: null, // 'C'\n avgHumid: null, // '%'\n isCluster: isCluster,\n avgPressure: null, // kPa\n min: min,\n max: max,\n chartValues: avg\n });\n }}>\n {pointCount}\n \n );\n }\n\n return (\n {\n e.stopPropagation();\n\n markerOnClick({\n id: cluster.properties.nodeId,\n coords: [lng, lat],\n data: [cluster],\n avgTemp: null, // 'C'\n avgHumid: null, // '%'\n isCluster: isCluster,\n avgPressure: null, // kPa\n min: {},\n max: {},\n chartValues: cluster.properties.value\n });\n }}\n />\n );\n }) : null}\n \n {activeControl === 1 &&\n \n
\n
\n \n MAX\n \n \n
\n \n
\n {errors.max &&

{errors.max.message}

}\n
\n }\n \n );\n}\n","import React from 'react';\nimport { Gauge } from './Styles';\nimport avgIcon from '../Assets/Icons/AVG_Callout.svg';\n\n// props: cluster, name, min, max, unit, chartWidth\nexport default function Sensor({\n cluster, max, min, val, unit, name, chartWidth\n}) {\n\n // function to calcualte hue value of the gauge filler\n const percentToHue = (percent) => {\n const hue = (0 - 120) * (percent / 100) + 120;\n\n return `hsl(${hue},100%, 40%)`;\n }\n\n // 1. calculate the percent of the \"props.val\" between \"props.min\" and\n // \"props.max\".\n const percent = ((val - min) * 100) / (max - min);\n\n // 2. Divide turn by 200 which to get proper decimal for % of semicircle\n // 3. Calculate the hsl string using hue with calculated \"percent\"\n const turn = percent/200;\n const fill = percentToHue(percent);\n\n return (\n
\n {cluster ? clusterIcon : null}\n
\n {name}\n
\n {min ? `MIN: ${min.toFixed(3)}` : null }\n {max ? `MAX: ${max.toFixed(3)}` : null }\n
\n
\n { cluster ? \n \n {unit}\n
\n
\n
{val?.toFixed(3)}
\n
\n
\n :\n <>\n {val ? val.toFixed(3) : '-'}\n {unit}\n \n }\n
\n
\n );\n}\n","import React from 'react';\nimport exportData from '../Assets/Icons/exportData.svg';\nimport { dateParser } from './utility';\nimport { Button, Img } from './Styles';\n\n// props: (data: Object, units: Array, name: String, node: Bool, text: String,\n// timezone: String)\nexport default function Export({ data, units, name, node, text, offset, \n timezone, width}) {\n\n const onClick = () => {\n // 1. build data\n let csv = `data:text/csv;charset=utf-8,`;\n // 1.1 default headers\n csv += `Date,Time ${timezone},Timestamp,`;\n // 1.2 according to the node boolean build appropriate data\n csv = node ? buildNodeData(csv) : buildFlightData(csv);\n\n // encode csv\n const encodedUri = encodeURI(csv);\n \n // create button in dom with download method, click it and remove it\n const link = document.createElement('a');\n link.setAttribute('href', encodedUri);\n link.setAttribute('download', `${name}.csv`);\n document.body.appendChild(link);\n link.click();\n link.remove();\n }\n\n const buildNodeData = (csv) => {\n // 1.1 build name headers\n for (let i in data[0].properties.value) {\n csv += `${data[0].properties.value[i].sensor_name},`;\n }\n csv += `Longitude,Latitude\\n`;\n \n // 1.2.1 add altitude unit since it was added to sensors after request \n units['alt'] = '-';\n // 1.2.2 build unit name headers\n csv += `MM/DD/YYYY,HH:MM:SS,Epoch,`;\n for (let i in data[0].properties.value) {\n csv += `${units[i]},`;\n }\n // 1.2.3 add dashes for units of longitude and latitude units\n csv +=`-,-,\\n`;\n\n // 1.3 Add data to csv\n for (let i in data) {\n\n // 1.3.1 date, time, timestamp first\n const timestampWithOffset = data[i].properties.nodeId + offset;\n const date = dateParser(timestampWithOffset * 1000, 1, 1);\n csv += `${date.slice(0, 10)},`;\n csv += `${date.slice(date.length - 8)},`;\n csv += `${data[i].properties.nodeId},`;\n\n // 1.3.2 sensor values second\n for (let j in data[i].properties.value) {\n csv += `${data[i].properties.value[j].value},`;\n }\n\n // 1.3.3 add coords at the end\n csv += `${data[i].geometry.coordinates[0]},`;\n csv += `${data[i].geometry.coordinates[1]},\\n`;\n }\n\n return csv;\n }\n\n const buildFlightData = (csv) => {\n // 1.1 build name headers from the first sample of data\n for (const i in data[0].values) {\n csv += `${data[0].values[i].sensor_name},`; \n }\n csv += `Altitude,Longitude,Latitude\\n`;\n\n // 1.2 Build unit name headers from @units\n csv += `MM/DD/YYYY,HH:MM:SS,Epoch,`;\n for (const i in data[0].values) {\n csv += `${units[i]},`;\n }\n csv += `-,-,-\\n`;\n\n // 1.3 add data to csv\n for (const i in data) {\n // 1.3.1 date, time, timestamp first\n const timestampWithOffset = data[i].timestamp + offset;\n const date = dateParser(timestampWithOffset * 1000, 1, 1);\n csv += `${date.slice(0, 10)},`;\n csv += `${date.slice(date.length - 8)},`;\n csv += `${data[i].timestamp},`;\n\n // 1.3.2 sensor values second\n for (let j in data[i].values) {\n csv += `${data[i].values[j].value},`;\n }\n\n // 1.3.3 lat lng alt \n csv += `${data[i].altitude},`;\n csv += `${data[i].longitude},`;\n csv += `${data[i].latitude},\\n`;\n }\n\n return csv;\n }\n\n return (\n \n );\n}\n","import React, { useState, useEffect } from 'react';\r\nimport GoogleMap from '../Containers/GoogleMap';\r\nimport Select from '../Containers/Select';\r\nimport downShevron from '../Assets/Icons/InnerBox_Down.svg';\r\nimport upShevron from '../Assets/Icons/InnerBox_Up.svg';\r\nimport closeTab from '../Assets/Icons/close.png';\r\nimport Sensor from '../Containers/Sensor';\r\nimport Export from '../Containers/Export';\r\nimport { doFetch } from '../Containers/calls';\r\nimport { dateParser } from '../Containers/utility';\r\nimport { useAuth } from '../Containers/Context/auth';\r\nimport { Page, ProjectWrap, Ul, FlightMenu, NodeMenu, Sensors, \r\n RowCheckbox, Img\r\n} from '../Containers/Styles';\r\n\r\n// props: match.params.id\r\nexport default function Project({ match }) {\r\n const { resetTokens } = useAuth();\r\n const projectId = match.params.project;\r\n const flightId = localStorage.getItem('flightId') || null;\r\n const [project, setProject] = useState({});\r\n const [flight, setFlight] = useState({});\r\n const [selectedFlight, setSelectedFlight] = useState(flightId);\r\n const [nodeInfo, setNodeInfo] = useState({\r\n id: null,\r\n coords: [],\r\n data: [],\r\n avgTemp: null, // 'C'\r\n avgHumid: null, // '%'\r\n avgPressure: null, // kPa\r\n chartValues: {},\r\n isCluster: null,\r\n max: {},\r\n min: {}\r\n });\r\n const [displayFlightmenuFlag, setDisplayFlightmenuFlag]= useState(1);\r\n\r\n // new flight request\r\n useEffect(() => {\r\n // don't call api if selectedFlight is empty. It is the case on init\r\n if (!selectedFlight) {\r\n return;\r\n }\r\n\r\n const abortControl = new AbortController();\r\n const reqUrl = `/travel_session/${selectedFlight}?sort_by=timestamp`;\r\n\r\n doFetch(`GET`, reqUrl, abortControl.signal)\r\n .then(flight => {\r\n\r\n // clear nodeInfo\r\n updateNodeInfo(null);\r\n \r\n // remove sensors that are not present in the current flight\r\n // for consistency \r\n for (let i = 0; i < flight.sensors.length; ++i) {\r\n let id = flight.sensors[i].id;\r\n\r\n // compare sensor id with sample sensor id. If it exists, set it\r\n // false as flag\r\n for (let j in flight.samples[0].values) {\r\n if (id === j) {\r\n id = 0;\r\n }\r\n }\r\n\r\n // reduce the count after splicing, additionally removes battery\r\n if (id || flight.sensors[i].name === 'BAT') {\r\n flight.sensors.splice(i, 1);\r\n --i; \r\n }\r\n }\r\n\r\n // set flight in localstorage as well\r\n localStorage.setItem('flightId', selectedFlight);\r\n setFlight(flight);\r\n })\r\n .catch(err => {\r\n console.log(err);\r\n if (err.status === 401) {\r\n resetTokens();\r\n }\r\n });\r\n \r\n return () => {\r\n abortControl.abort();\r\n };\r\n\r\n },[selectedFlight]);\r\n\r\n const updateNodeInfo = (val) => {\r\n if (val) {\r\n setNodeInfo(val);\r\n } else {\r\n setNodeInfo({\r\n id: null,\r\n coords: [],\r\n data: [],\r\n avgTemp: null, // 'C'\r\n avgHumid: null, // '%'\r\n avgPressure: null, // kPa\r\n chartValues: {},\r\n isCluster: null,\r\n max: {},\r\n min: {}\r\n });\r\n }\r\n }\r\n \r\n const getSensorFromChartValues = (short_name, full_name, unit) => {\r\n for (let i in nodeInfo.chartValues) {\r\n if (nodeInfo.chartValues[i].sensor_name === short_name) {\r\n return (\r\n
  • \r\n AVG {full_name}: {\r\n nodeInfo.chartValues[i].value.toFixed(3)\r\n } {unit}\r\n
  • \r\n )\r\n }\r\n }\r\n return null;\r\n }\r\n \r\n useEffect(() => {\r\n const abortControl = new AbortController();\r\n\r\n doFetch(`GET`, `/project/${projectId}`, abortControl.signal)\r\n .then(project => {\r\n project['flightList'] = project.travel_sessions.map(flight => ({\r\n label: dateParser(flight.start_timestamp * 1000, 1),\r\n value: flight.id\r\n }))\r\n setProject(project);\r\n })\r\n .catch(err => {\r\n console.log(err);\r\n if (err.status === 401) {\r\n resetTokens();\r\n }\r\n });\r\n\r\n return () => {\r\n abortControl.abort();\r\n };\r\n }, []);\r\n\r\n // makes request to the server to set the project to favourite state, and\r\n // asyncronously updates the star of the project.\r\n const favClickHandler = () => {\r\n const abortControl = new AbortController();\r\n\r\n doFetch('POST', `/project/${projectId}/favourite`, abortControl.signal)\r\n .then(json => {\r\n })\r\n .catch(err => {\r\n console.log(err)\r\n if (err.status === 401) {\r\n resetTokens();\r\n }\r\n });\r\n \r\n return () => {\r\n abortControl.abort();\r\n };\r\n }\r\n\r\n // displays the time/timeRange of selected point or cluster in header\r\n const displaySensorHeader = () => {\r\n if (nodeInfo.id) {\r\n if (nodeInfo.isCluster) {\r\n const timestampArray = nodeInfo.data.map(point => {\r\n return point.properties.nodeId;\r\n });\r\n const first = dateParser(Math.min(...timestampArray) * 1000, 1, 1);\r\n const last = dateParser(Math.max(...timestampArray) * 1000, 1, 1);\r\n\r\n return `Selected Cluster from ${\r\n first.substring(11, first.length)\r\n } to ${last.substring(11, last.length)}` \r\n } else {\r\n const dateStr = dateParser(nodeInfo.id * 1000, 1, 1);\r\n return `Selected Cluster at ${dateStr.substring(11, dateStr.length)}`;\r\n }\r\n }\r\n }\r\n\r\n return(\r\n \r\n \r\n
    \r\n \r\n
    \r\n { nodeInfo.id ? \r\n \r\n toggleFlightMenu\r\n
      \r\n
    • \r\n AVG Altitude: {\r\n nodeInfo.chartValues.alt.value.toFixed(2)\r\n }\r\n
    • \r\n
    • \r\n AVG Latitude: {nodeInfo.coords[1]}\r\n
    • \r\n
    • \r\n AVG Longitude: {nodeInfo.coords[0]}\r\n
    • \r\n
    \r\n \r\n
    \r\n {displaySensorHeader()}\r\n
    \r\n
    \r\n {\r\n flight.sensors.length && flight.samples.length ?\r\n flight.sensors.map((s, i) => {\r\n if (s.name !== 'BAT') {\r\n return (\r\n \r\n );\r\n }\r\n }) \r\n : null\r\n }\r\n
    \r\n
    \r\n
    \r\n \r\n [s.id, s.unit]))}\r\n offset={flight.timezone_offset}\r\n timezone={flight.timezone_id}/>\r\n
    \r\n
    \r\n : \r\n }\r\n { project.id ?\r\n \r\n
    \r\n {project.name}\r\n
    \r\n
      \r\n
    • \r\n Total Flights: \r\n {project.travel_sessions.length}\r\n
    • \r\n
    • Total KM Flown: {\r\n project.travel_sessions.length ? \r\n project.travel_sessions\r\n .map(f => f.distance)\r\n .reduce((o, t) => o + t)\r\n .toFixed(3)\r\n : null\r\n }
    • \r\n
    • \r\n Total Time Flown: \r\n {\r\n project.time_length ? \r\n {Math.ceil(project.time_length / 60)} minute(s)\r\n : null\r\n }\r\n
    • \r\n
    \r\n \r\n \r\n
    \r\n :\r\n null\r\n }\r\n
    setDisplayFlightmenuFlag(!displayFlightmenuFlag)}>\r\n toggleFlightMenu\r\n
    \r\n
    \r\n
    \r\n );\r\n}\r\n\r\n","import React, { useRef, useState, useLayoutEffect } from 'react';\nimport * as am4core from \"@amcharts/amcharts4/core\";\nimport * as am4charts from \"@amcharts/amcharts4/charts\";\nimport am4themes_dark from '@amcharts/amcharts4/themes/dark';\n//import am4themes_animated from \"@amcharts/amcharts4/themes/animated\";\n\n// props: flightData: Object\nexport default function LineChart({ flightData, legendFlag }) {\n \n am4core.useTheme(am4themes_dark);\n //am4core.useTheme(am4themes_animated);\n const colors = ['#2196f3','#4caf50','#607d8b','#ffeb3b','#F4364C','#ff9800','#00bcd4',\n '#ab47bc','#795548','#e91e63','#cddc39','#ff7676','#6d712e','#673ab7','#800020',\n '#009688','#3f51b5','#76ff03','#ffff8d','#d50000','#FA4616','#82A3FF','#9873AC',\n '#CDC4AA','#862633','#D9027D','#FFBCD9','#36454F','#ADDFB3','#FFB673','#5D3754',\n '#AC9F3C','#06038D','#44693D','#3C1321','#36454F','#9FE2BF','#CB6015','#2E1A47',\n '#154734'\n ];\n /** 40 colors\n * blue, green, bluegrey, yellow, Amaranth, orange, cyan, \n * purple, brown, pink, lime, salmonPink, oliveGreen, deepPurlple, burgendy,\n * teal, indigo, lightGreen, lightYellow, red, orangeRed, CornflowerBlue, lavender,\n * oatmeal, Maroon, Fuchsia, cottonCandyPink, CharcoalGray, Celadon,apricot, eggplant,\n * brass,darkblue, hunterGreen, darkChocoBrown, CharcoalGray, SeafoamGreen, burntOrange, midnightPurple, \n * darkGreen\n * */ \n const chart = useRef(null);\n\n const addSeries = (ch, yAxes, sensor, color) => {\n // add lines to the chart\n let line = ch.series.push(new am4charts.LineSeries());\n line.dataFields.dateX = \"date\";\n line.name = sensor.name;\n line.fill = color;\n line.stroke = color;\n line.dataFields.valueY = sensor.name;\n line.strokeWidth = 2;\n line.tooltipText = \"{name}: {valueY}{yAxis.name}\";\n line.yAxis = yAxes[sensor.unit];\n\n // display yAxes of the line when its toggled on\n line.events.on('shown', function() {\n // change flag since chart doesn't change it by default for some\n // reason\n line.hidden = 0;\n\n // display yAxis\n line.yAxis.disabled = 0;\n });\n\n // hides yAxis when when all related series are hidden \n line.events.on('hidden', function() {\n // changes flag since chart doesn't change it by default for some\n // reason\n line.hidden = 1;\n\n // loops through list of sensors in the chart and checks if \n // the other sensors with the same yAxis are hidden. If at least\n // one is showing it will keep the yAxis. \n for(let j in ch.series.values) {\n if (ch.series.values[j].yAxis.name === sensor.unit &&\n !ch.series.values[j].hidden && \n ch.series.values[j].name !== 'Toggle All') {\n return;\n }\n }\n\n // If all of them are hidden it will hide the yAxis as well.\n line.yAxis.disabled = 1;\n });\n \n // add bullets\n //let bullet = line.bullets.push(new am4charts.CircleBullet());\n };\n const addYAxis = (ch, yAxes, sensor, yAxisLocation) => {\n let valueAxis = ch.yAxes.push(new am4charts.ValueAxis());\n valueAxis.renderer.opposite = yAxisLocation; \n valueAxis.tooltip.disabled = true;\n valueAxis.name = sensor.unit;\n valueAxis.layout = 'absolute';\n valueAxis.title.rotation = 0;\n valueAxis.title.align = 'center';\n valueAxis.title.valign = 'bottom';\n valueAxis.title.dy = 40;\n valueAxis.tooltip.dx = 45;\n valueAxis.renderer.line.strokeOpacity = 1;\n \n if (!legendFlag) {\n valueAxis.renderer.line.disabled = true; //disables axis line\n valueAxis.renderer.labels.template.disabled = true; //disables labels\n valueAxis.renderer.grid.template.disabled = true; //disables grid\n } else {\n valueAxis.title.text = `${sensor.unit}`;\n }\n\n yAxes[sensor.unit] = valueAxis;\n };\n\n // adds one more empty series to have toggle button in legend\n const addToggleSensors = (ch, yAxes) => {\n if (flightData.sensors) {\n let toggle = ch.series.push(new am4charts.LineSeries());\n toggle.name = 'Toggle Sensors';\n toggle.dataFields.dateX = \"date\";\n toggle.fill = '#ffffff';\n toggle.stroke = '#ffffff';\n toggle.dataFields.valueY = 'void';\n toggle.yAxis = yAxes[flightData.sensors[0].unit];\n\n toggle.events.on('hidden', function() {\n for (let i in ch.series.values) {\n ch.series.values[i].hide();\n ch.series.values[i].hidden = 1;\n }\n for (let i in ch.yAxes.values) {\n ch.yAxes.values[i].disabled = 1;\n }\n });\n\n toggle.events.on('shown', function() {\n for (let i in ch.series.values) {\n ch.series.values[i].show();\n ch.series.values[i].hidden = 0;\n }\n for (let i in ch.yAxes.values) {\n ch.yAxes.values[i].disabled = 0;\n }\n });\n }\n }\n\n // creation of the chart\n useLayoutEffect(() => {\n if (!flightData || !flightData.samples) {\n return;\n }\n\n let ch = am4core.create(\"chartDiv\", am4charts.XYChart);\n am4core.options.autoSetClassName = true;\n am4core.DateFormatter.timezone = flightData.timezone_id;\n let data = [];\n let visits = 10;\n\n // get points \n for (let i in flightData.samples) {\n let sample = {\n date: new Date(flightData.samples[i].timestamp * 1000)\n };\n\n for (let j in flightData.samples[i].values) {\n const value = flightData.samples[i].values[j];\n\n // remove battery\n if (value.sensor_name !== 'BAT') {\n\n sample[value.sensor_name] = value.value;\n }\n }\n\n // Add alitiude to data separately\n sample['ALT'] = flightData.samples[i].altitude; \n\n data.push(sample);\n }\n\n // add data\n ch.data = data;\n\n // add xAxis\n let dateAxis = ch.xAxes.push(new am4charts.DateAxis());\n dateAxis.renderer.grid.template.location = 0;\n dateAxis.groupData = true;\n\n // add yAxes\n let yAxes = {};\n for (let i in flightData.sensors) {\n let sameUnitFlag = 0;\n const sensor = flightData.sensors[i];\n\n // find unique unit to create yAxis with\n for (let j in yAxes) { \n if (j === sensor.unit) { \n sameUnitFlag = 1;\n break;\n }\n }\n\n // if the unit is unique\n if (!sameUnitFlag) {\n addYAxis(ch, yAxes, sensor, i%2);\n }\n }\n\n addToggleSensors(ch, yAxes);\n \n // add lines \n for (let i in flightData.sensors) {\n addSeries(ch, yAxes, flightData.sensors[i], colors[i]);\n }\n\n // add Altitude to the charts \n // 1. yAxis\n addYAxis(ch, yAxes, { name: 'ALT', unit: 'M' }, 1);\n\n // 2. series\n addSeries(ch, yAxes, { name: 'ALT', unit: 'M' }, '#ffffff');\n\n // add legend\n if (legendFlag) {\n ch.legend = new am4charts.Legend();\n ch.legend.labels.template.text = '[bold]{name}[/]';\n } else {\n console.log(ch.yAxes);\n //ch.yAxes.disabled = true; //disables axis line\n }\n\n // add cursor\n ch.cursor = new am4charts.XYCursor();\n\n // save chart ref\n chart.current = ch;\n\n return () => {\n ch.dispose();\n };\n }, [flightData, legendFlag]);\n\n return (\n
    \n ); \n}\n\n","import React, { useState, useEffect } from 'react';\r\nimport { \r\n Page, AnalysisWrap, Sensors, ChartStyle, Button \r\n} from '../Containers/Styles';\r\nimport Select from '../Containers/Select';\r\nimport bgImg from '../Assets/map.png';\r\nimport Sensor from '../Containers/Sensor';\r\nimport LineChart from '../Containers/LineChart';\r\nimport GoogleMap from '../Containers/GoogleMap';\r\nimport Export from '../Containers/Export';\r\nimport { doFetch } from '../Containers/calls';\r\nimport { dateParser } from '../Containers/utility';\r\nimport { useAuth } from '../Containers/Context/auth';\r\n\r\n// props: match\r\nexport default function Analysis({ match }) {\r\n const { resetTokens } = useAuth();\r\n const projectId = match.params.project;\r\n const flightId = localStorage.getItem('flightId') || null;\r\n const [project, setProject] = useState({});\r\n const [selectedFlight, setSelectedFlight] = useState(flightId);\r\n const [flight, setFlight] = useState({});\r\n const [nodeInfo, setNodeInfo] = useState({\r\n id: null,\r\n coords: [],\r\n data: [],\r\n avgTemp: null, // 'C'\r\n avgHumid: null, // '%'\r\n avgPressure: null, // kPa\r\n chartValues: {},\r\n isCluster: null,\r\n max: {},\r\n min: {}\r\n });\r\n const [chartLegendFlag, setChartLegendFlag] = useState(1);\r\n\r\n const updateNodeInfo = (val) => {\r\n if (val) {\r\n setNodeInfo(val);\r\n } else {\r\n setNodeInfo({\r\n id: null,\r\n coords: [],\r\n data: [],\r\n avgTemp: null, // 'C'\r\n avgHumid: null, // '%'\r\n avgPressure: null, // kPa\r\n chartValues: {},\r\n isCluster: null,\r\n max: {},\r\n min: {}\r\n });\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n const abortControl = new AbortController();\r\n\r\n doFetch(`GET`, `/project/${projectId}`, abortControl.signal)\r\n .then(project => {\r\n\r\n // if project has flights, pulls first flight and fills dropdown list\r\n // with flights\r\n if (project.travel_sessions.length) {\r\n project['flightList'] = project.travel_sessions.map(flight => ({\r\n label: dateParser(flight.start_timestamp * 1000, 1),\r\n value: flight.id\r\n }));\r\n setProject(project);\r\n } \r\n })\r\n .catch(err => {\r\n console.log(err);\r\n if (err.status === 401) {\r\n resetTokens();\r\n }\r\n });\r\n\r\n return () => {\r\n abortControl.abort(); \r\n };\r\n }, []);\r\n\r\n useEffect(() => {\r\n const abortControl = new AbortController();\r\n \r\n if (selectedFlight) {\r\n updateNodeInfo();\r\n\r\n doFetch(`GET`, `/travel_session/${selectedFlight}?sort_by=timestamp`)\r\n .then(flight => {\r\n // remove sensors that are not present in the current flight\r\n // for consistency, and 'BAT' sensor\r\n for (let i = 0; i < flight.sensors.length; ++i) {\r\n let id = flight.sensors[i].id;\r\n\r\n // compare sensor id with sample sensor id. If it exists, set it\r\n // false as flag\r\n for (let j in flight.samples[0].values) {\r\n if (id === j) {\r\n id = 0;\r\n }\r\n }\r\n\r\n // reduce the count after splicing, additionally removes battery\r\n if (id || flight.sensors[i].name === 'BAT') {\r\n flight.sensors.splice(i, 1);\r\n --i;\r\n }\r\n }\r\n\r\n // set flight in localstorage as well\r\n localStorage.setItem('flightId', selectedFlight);\r\n setFlight(flight);\r\n })\r\n .catch(err => {\r\n console.log(err);\r\n if (err.status === 401) {\r\n resetTokens();\r\n }\r\n });\r\n }\r\n return () => abortControl.abort(); \r\n }, [selectedFlight]);\r\n\r\n const displayNodeInfo = () => {\r\n if (flight.sensors) {\r\n if (nodeInfo.id) {\r\n return flight.sensors.map(s => (\r\n \r\n ));\r\n } else {\r\n return flight.sensors.map(s => (\r\n \r\n ));\r\n }\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n // displays the time/timeRange of selected point or cluster in header\r\n const displaySensorHeader = () => {\r\n if (nodeInfo.id) {\r\n if (nodeInfo.isCluster) {\r\n const timestampArray = nodeInfo.data.map(point => {\r\n return point.properties.nodeId;\r\n });\r\n const first = dateParser(Math.min(...timestampArray) * 1000, 1, 1);\r\n const last = dateParser(Math.max(...timestampArray) * 1000, 1, 1);\r\n\r\n return `Selected Cluster from ${\r\n first.substring(11, first.length)\r\n } to ${last.substring(11, last.length)}` \r\n } else {\r\n const dateStr = dateParser(nodeInfo.id * 1000, 1, 1);\r\n return `Selected Cluster at ${dateStr.substring(11, dateStr.length)}`;\r\n }\r\n }\r\n }\r\n \r\n return(\r\n \r\n \r\n \r\n {\r\n project.flightList && project.flightList.length ? \r\n
    \r\n Analysis\r\n \r\n \r\n
    Forgot Password? \r\n Start here.\r\n
    \r\n \r\n \r\n { warning ? \r\n \r\n {warning} \r\n support@scentroid.com\r\n : \r\n null\r\n }\r\n \r\n \r\n SCENTROiD\r\n
  • \r\n \r\n mail\r\n \r\n \r\n twit\r\n \r\n \r\n yt\r\n \r\n \r\n ig\r\n \r\n \r\n li\r\n \r\n \r\n fb\r\n \r\n
  • \r\n \r\n );\r\n}\r\n","import React from 'react';\r\nimport gifImage from '../Assets/404.gif';\r\nimport { Page, NotFoundWrap, Img } from '../Containers/Styles';\r\nimport { Link } from 'react-router-dom';\r\n\r\nexport default function NotFound() {\r\n return(\r\n \r\n \r\n
    \r\n 4\r\n notFoundGif\r\n 4\r\n
    \r\n \r\n
    \r\n
    \r\n );\r\n}\r\n","import React, { useState } from 'react';\r\nimport { Route, Switch, BrowserRouter as Router } from 'react-router-dom';\r\nimport PrivateRoute from './Containers/PrivateRoute'\r\nimport Home from './Pages/Home';\r\nimport Navbar from './Containers/Navbar';\r\nimport Project from './Pages/Project';\r\nimport Analysis from './Pages/Analysis';\r\nimport Alerts from './Pages/Alerts';\r\nimport Login from './Pages/Login';\r\nimport NotFound from './Pages/NotFound';\r\nimport { AuthContext } from './Containers/Context/auth';\r\nimport { Fonts, Main } from './Containers/Styles';\r\nimport { doFetch } from './Containers/calls';\r\nimport { SWRConfig } from 'swr';\r\n\r\nimport { datadogRum } from '@datadog/browser-rum';\r\n\r\ndatadogRum.init({\r\n applicationId: 'f600b9b7-f290-4293-baed-0cd55e94b01f',\r\n clientToken: 'pubd27b7a7eae09ee2ef80ca67d9f1ff7f8',\r\n site: 'datadoghq.com',\r\n service:'drims2',\r\n\r\n // Specify a version number to identify the deployed version of your application in Datadog\r\n // version: '1.0.0',\r\n sampleRate: 100,\r\n premiumSampleRate: 100,\r\n trackInteractions: true,\r\n defaultPrivacyLevel:'mask-user-input'\r\n});\r\n\r\ndatadogRum.startSessionReplayRecording();\r\n\r\nfunction App() {\r\n const userToken = localStorage.getItem('token') || null;\r\n const [authToken, setAuthToken] = useState(userToken);\r\n\r\n const setTokens = (data) => {\r\n localStorage.setItem('token', data);\r\n setAuthToken(data);\r\n }\r\n\r\n const resetTokens = () => {\r\n doFetch('GET', '/auth/logout')\r\n .then(json => {\r\n console.log('logout ok', json)\r\n localStorage.clear();\r\n setAuthToken(null);\r\n })\r\n .catch(err => console.log('logout had err: ', err));\r\n }\r\n\r\n // fetcher for global SWRConfig with error handling\r\n /*\r\n const fetcher = (...args) => {\r\n // add authorization \r\n if (localStorage.token) {\r\n myHeaders['Authorization'] = 'Bearer ' + localStorage.token;\r\n }\r\n\r\n return fetch(...args, \r\n { \r\n credentials: 'include', \r\n headers: myHeaders,\r\n }\r\n ).then(res => {\r\n if (res.ok) {\r\n return res.json();\r\n }\r\n if (res.status === 401) {\r\n resetTokens();\r\n }\r\n throw new Error([res.status, res.statusText]);\r\n })\r\n }\r\n \r\n \r\n */\r\n\r\n return (\r\n
    \r\n \r\n \r\n \r\n { \r\n authToken ? \r\n \r\n :
    \r\n }\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
    \r\n );\r\n}\r\n\r\nexport default App;\r\n\r\n","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport * as serviceWorker from './serviceWorker';\r\nimport App from './App';\r\nimport 'normalize.css';\r\n\r\nReactDOM.render(, document.getElementById('root'));\r\n\r\n// If you want your app to work offline and load faster, you can change\r\n// unregister() to register() below. Note this comes with some pitfalls.\r\n// Learn more about service workers: https://bit.ly/CRA-PWA\r\nserviceWorker.unregister();\r\n"],"sourceRoot":""}