{"version":3,"sources":["map/components/Map.module.css","common/Header.module.css","roadClosures/components/ClosureList.module.css","search/components/SearchResult.module.css","constants.js","roadClosures/actionTypes.js","roadClosures/reducer.js","search/reducer.js","search/actionTypes.js","map/reducer.js","map/actionTypes.js","registerServiceWorker.js","hooks/useFetch.js","hooks/useRecurrantFetch.js","map/selectors.js","map/hooks.js","map/actions.js","roadClosures/actions.js","roadClosures/selectors.js","roadClosures/hooks.js","common/BaseLayout.js","tabs/hooks.js","tabs/components/Tab.js","tabs/components/TabMenu.js","tabs/components/TabPanel.js","tabs/components/TabPanelContainer.js","hooks/useMedia.js","map/constants.js","map/components/Map.js","map/components/Zoom.js","map/components/BasemapToggle.js","map/components/Compass.js","map/components/GraphicLayer.js","map/components/RoadClosuresLayer.js","search/actions.js","search/selectors.js","map/components/AddressSearchLayer.js","search/hooks.js","common/Header.js","common/FormattedDate.js","roadClosures/components/ClosureListItem.js","roadClosures/components/ClosureList.js","common/TextInput.js","search/components/SearchResult.js","search/components/SearchPanel.js","App.js","webpack:///./src/index.js?b635","store.js","tabs/components/Tabs.module.css","common/BaseLayout.module.css","common/Input.module.css","roadClosures/components/ClosureListItem.module.css","search/components/SearchPanel.module.css","App.module.css"],"names":["module","exports","BASE_URL","document","getElementsByTagName","getAttribute","FETCH_START","FETCH_SUCCESS","FETCH_FAILURE","NAME","initialSelected","closureIds","current","roadClosures","combineReducers","byId","state","action","type","ActionTypes","closures","forEach","e","id","closureId","roadSegments","map","segment","hover","segmentId","allKeys","roadClosuresIsLoading","selected","resultIds","search","console","log","results","i","resultsIsLoading","initialState","view","reducer","isLocalhost","Boolean","window","location","hostname","match","registerValidSW","swUrl","navigator","serviceWorker","register","then","registration","onupdatefound","installingWorker","installing","onstatechange","controller","catch","error","response","isLoading","useFetch","url","options","deps","predicate","useState","setState","refreshCount","setRefreshCount","refresh","useCallback","count","useMemo","AbortController","cancel","abort","useEffect","a","onStart","fetch","signal","res","ok","json","onSuccess","statusText","onError","fetchData","useRecurrantFetch","refreshSeconds","errorRefreshSeconds","Date","getTime","nextFetch","setNextFetch","Infinity","waitTime","timeoutHandle","setTimeout","clearTimeout","getMap","getView","ready","classes","getEsri1","Promise","resolve","reject","esriRequire","Array","prototype","slice","call","arguments","result","fullClassName","index","className","exec","exception","sleep","ms","getEsri","useEsri","dependencies","useMap","dispatch","useDispatch","useSelector","setMapAndView","selectClosures","getClosureIds","getClosureById","createSelector","getClosures","getClosuresIsLoading","getSelectedClosureIds","getCurrentSelectedIndex","getSelectedClosureId","eventIds","useRoadClosuresFetch","selectedIds","length","fetchSuccess","fetchFail","BaseLayout","title","children","styles","container","header","src","alt","logo","headerTitle","href","headerTitleLink","useIsSelected","path","currentPath","useLocation","pathname","matchPath","isExact","strict","Tab","label","icon","defaultPath","history","useHistory","isSelected","select","push","useTab","iSelected","isDefaultPath","tabSelected","tab","onClick","tabLabel","TabMenu","tabMenu","TabPanel","Component","component","rest","tabPanel","TabPanelContainer","useMedia","query","mediaQuery","matchMedia","getResult","matches","setResult","handler","addListener","removeListener","PROXY_URL","esriReqs","withRouter","basemap","padding","Map","MapView","urlUtils","isDesktop","addProxyRule","urlPrefix","proxyUrl","viewOptions","center","zoom","ui","popup","dockOptions","position","actions","removeAll","kids","React","Children","child","cloneElement","Zoom","remove","move","Toggle","next","BasemapToggle","basemapToggle","nextBasemap","add","CompassWidget","Compass","compass","GraphicLayer","graphics","onSelect","onDeselect","Graphic","GraphicsLayer","layer","setLayer","layerId","newLayer","newGraphics","graphic","geometry","symbol","attributes","data","addMany","on","event","screenPoint","x","y","mapPoint","longitude","latitude","hitTest","matching","filter","getSegmentSymbol","isHovered","color","width","style","getSegmentGeometry","paths","getSegmentAttributes","closure","RoadClosuresLayer","Polyline","clear","ids","useClosuresMap","editorIsOpen","getIsSelected","flatMap","some","g","find","goTo","selectResults","getResultIds","getResultById","getResults","getResultsIsLoading","getSelectedResultIds","getSelectedResultId","getResultSymbol","resultId","height","yoffset","getResultGeometry","getResultAttributes","AddressSearchLayer","useResultsMap","Header","FormattedDate","date","formattedDate","moment","utc","format","fromNow","getIconFromReason","reason","ClosureListItem","useClosure","closedDate","roadNames","includes","name","join","item","timestamp","ClosureList","unsortedIds","sort","b","isSame","isBefore","useClosuresList","list","key","TextInput","value","onChange","placeholder","disabled","button","onKeyPressed","defaultContainer","inputWithButton","input","target","onKeyPress","required","inputButton","SearchResult","useResult","address","SearchPanel","setQuery","method","headers","body","JSON","stringify","useAddressSearch","score","useResultsList","App","mapPadding","top","left","right","bottom","tabBar","sideBar","Bugsnag","start","apiKey","plugins","BugsnagPluginReact","ErrorBoundary","getPlugin","createErrorBoundary","store","reducers","RoadClosuresReducerName","RoadClosuresReducer","MapReducer","SearchReducer","middleware","thunk","enhancers","rootReducer","createStore","compose","applyMiddleware","configureStore","initialReduxState","ReactDOM","render","basename","getElementById","URL","process","origin","addEventListener","status","get","indexOf","unregister","reload","checkValidServiceWorker","registerServiceWorker"],"mappings":"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","file":"static/js/main.06ab54b1.chunk.js","sourcesContent":["// extracted by mini-css-extract-plugin\nmodule.exports = {\"map\":\"Map_map__Le3cC\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"header\":\"Header_header__3vxgv\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"list\":\"ClosureList_list__1OxsG\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"item\":\"SearchResult_item__1xjeI\"};","export const BASE_URL = document\r\n .getElementsByTagName('base')[0]\r\n .getAttribute('href')\r\n\r\nexport const FETCH_STATUS = {\r\n NOT_YET_FETCHED: 0,\r\n FETCHING: 1,\r\n LOADED: 2,\r\n FETCH_FAILED: 3,\r\n}\r\n\r\nexport const EDIT_MODES = {\r\n NEW: 1,\r\n EDIT: 2,\r\n}\r\n\r\nexport const CLUSTER_LAYER = {\r\n INCIDENTS: 'INCIDENT_LAYER',\r\n AI: 'AI_LAYER',\r\n}\r\n\r\nexport const TWITTER_LAYER_ID = 23\r\n\r\nexport const MOBILE_SCREEN_WIDTH = 600\r\n\r\nexport const ICONS = {\r\n AI: {\r\n ACTIVE: { DIR: 'images/icons/ai/active/' },\r\n BORDERLESS: { DIR: 'images/icons/ai/borderless/' },\r\n POPUP: { DIR: 'images/icons/ai/popup/' },\r\n DIR: 'images/icons/ai/inactive/',\r\n },\r\n BORDERLESS: {\r\n BW: { DIR: 'images/icons/borderless/bw/' },\r\n DIR: 'images/icons/borderless/',\r\n },\r\n ACTIVE: { DIR: 'images/icons/active/' },\r\n SENT: { DIR: 'images/icons/sent/' },\r\n MUNICIPALITIES: {\r\n ACTIVE: { DIR: 'images/icons/municipalities/active/' },\r\n SENT: { DIR: 'images/icons/municipalities/sent/' },\r\n DIR: 'images/icons/municipalities/',\r\n },\r\n DIR: 'images/icons/',\r\n}\r\n","export const FETCH_START = 'roadClosures/FETCH_START'\r\nexport const FETCH_SUCCESS = 'roadClosures/FETCH_SUCCESS'\r\nexport const FETCH_FAILURE = 'roadClosures/FETCH_FAILURE'\r\n\r\nexport const SELECT_CLOSURES = 'roadClosures/SELECT_CLOSURES'\r\nexport const CLEAR_SELECTION = 'roadClosures/CLEAR_SELECTION'\r\n\r\nexport const HOVER_SEGMENT_START = 'roadClosures/HOVER_SEGMENT_START'\r\nexport const HOVER_SEGMENT_END = 'roadClosures/HOVER_SEGMENT_END'\r\n","import { combineReducers } from 'redux'\r\n\r\nimport * as ActionTypes from './actionTypes'\r\n\r\nexport const NAME = 'roadClosures'\r\n\r\nconst roadClosuresIsLoading = (state = true, action) => {\r\n switch (action.type) {\r\n case ActionTypes.FETCH_START:\r\n return true\r\n case ActionTypes.FETCH_FAILURE:\r\n case ActionTypes.FETCH_SUCCESS:\r\n return false\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nconst byId = (state = {}, action) => {\r\n switch (action.type) {\r\n case ActionTypes.FETCH_SUCCESS: {\r\n let byId = {}\r\n action.closures.forEach((e) => (byId[e.id] = e))\r\n return byId\r\n }\r\n case ActionTypes.HOVER_SEGMENT_START:\r\n if (!action.closureId) return state\r\n return {\r\n ...state,\r\n [action.closureId]: {\r\n ...state[action.closureId],\r\n roadSegments: state[action.closureId].roadSegments.map((segment) => {\r\n segment.hover = segment.hover || segment.id === action.segmentId\r\n return segment\r\n }),\r\n },\r\n }\r\n case ActionTypes.HOVER_SEGMENT_END:\r\n if (!action.closureId) return state\r\n return {\r\n ...state,\r\n [action.closureId]: {\r\n ...state[action.closureId],\r\n roadSegments: state[action.closureId].roadSegments.map((segment) => {\r\n segment.hover = segment.hover && segment.id !== action.segmentId\r\n return segment\r\n }),\r\n },\r\n }\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nconst allKeys = (state = [], action) => {\r\n switch (action.type) {\r\n case ActionTypes.FETCH_SUCCESS:\r\n return action.closures.map((e) => e.id)\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nconst initialSelected = { closureIds: [], current: 0 }\r\nconst selected = (state = initialSelected, action) => {\r\n switch (action.type) {\r\n case ActionTypes.SELECT_CLOSURES:\r\n return {\r\n closureIds: action.closureIds,\r\n current: 0,\r\n }\r\n case ActionTypes.CLEAR_SELECTION:\r\n return initialSelected\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nconst roadClosures = combineReducers({\r\n byId,\r\n allKeys,\r\n roadClosuresIsLoading,\r\n selected,\r\n})\r\n\r\nexport default roadClosures\r\n","import { combineReducers } from 'redux'\r\n\r\nimport * as ActionTypes from './actionTypes'\r\n\r\nexport const NAME = 'search'\r\n\r\nconst resultsIsLoading = (state = false, action) => {\r\n switch (action.type) {\r\n case ActionTypes.FETCH_START:\r\n return true\r\n case ActionTypes.FETCH_FAILURE:\r\n case ActionTypes.FETCH_SUCCESS:\r\n return false\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nconst byId = (state = {}, action) => {\r\n console.log('action', action)\r\n switch (action.type) {\r\n case ActionTypes.FETCH_SUCCESS: {\r\n let byId = {}\r\n action.results.forEach((e, i) => (byId[i] = { id: i, ...e }))\r\n return byId\r\n }\r\n case ActionTypes.HOVER_RESULT_START:\r\n if (!action.closureId) return state\r\n return {\r\n ...state,\r\n [action.closureId]: {\r\n ...state[action.closureId],\r\n roadSegments: state[action.closureId].roadSegments.map((segment) => {\r\n segment.hover = segment.hover || segment.id === action.segmentId\r\n return segment\r\n }),\r\n },\r\n }\r\n case ActionTypes.HOVER_RESULT_END:\r\n if (!action.closureId) return state\r\n return {\r\n ...state,\r\n [action.closureId]: {\r\n ...state[action.closureId],\r\n roadSegments: state[action.closureId].roadSegments.map((segment) => {\r\n segment.hover = segment.hover && segment.id !== action.segmentId\r\n return segment\r\n }),\r\n },\r\n }\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nconst allKeys = (state = [], action) => {\r\n switch (action.type) {\r\n case ActionTypes.FETCH_SUCCESS:\r\n return action.results.map((e, i) => i)\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nconst initialSelected = { resultIds: [], current: 0 }\r\nconst selected = (state = initialSelected, action) => {\r\n switch (action.type) {\r\n case ActionTypes.SELECT_RESULTS:\r\n return {\r\n resultIds: action.resultIds,\r\n current: 0,\r\n }\r\n case ActionTypes.CLEAR_SELECTION:\r\n return initialSelected\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nconst search = combineReducers({\r\n byId,\r\n allKeys,\r\n resultsIsLoading,\r\n selected,\r\n})\r\n\r\nexport default search\r\n","export const FETCH_START = 'search/FETCH_START'\r\nexport const FETCH_SUCCESS = 'search/FETCH_SUCCESS'\r\nexport const FETCH_FAILURE = 'search/FETCH_FAILURE'\r\n\r\nexport const SELECT_RESULTS = 'search/SELECT_RESULTS'\r\nexport const CLEAR_SELECTION = 'search/CLEAR_SELECTION'\r\n\r\nexport const HOVER_RESULT_START = 'search/HOVER_RESULT_START'\r\nexport const HOVER_RESULT_END = 'search/HOVER_RESULT_END'\r\n","import * as ActionTypes from './actionTypes'\r\n\r\nexport const NAME = 'map'\r\n\r\nconst initialState = {\r\n map: null,\r\n view: null,\r\n}\r\n\r\nconst reducer = (state = initialState, action) => {\r\n switch (action.type) {\r\n case ActionTypes.SET_MAP_AND_VIEW:\r\n return {\r\n map: action.map,\r\n view: action.view,\r\n }\r\n default:\r\n return state\r\n }\r\n}\r\n\r\nexport default reducer\r\n","export const SET_MAP_AND_VIEW = 'map/SET_MAP_AND_VIEW'\r\n","// In production, we register a service worker to serve assets from local cache.\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 the \"N+1\" visit to a page, since previously\r\n// cached resources are updated in the background.\r\n\r\n// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.\r\n// This link also includes instructions on opting out of this behavior.\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.1/8 is 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 default function register () {\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);\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/facebookincubator/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. Lets check if a service worker still exists or not.\r\n checkValidServiceWorker(swUrl);\r\n } else {\r\n // Is not local host. Just register service worker\r\n registerValidSW(swUrl);\r\n }\r\n });\r\n }\r\n}\r\n\r\nfunction registerValidSW (swUrl) {\r\n navigator.serviceWorker\r\n .register(swUrl)\r\n .then(registration => {\r\n registration.onupdatefound = () => {\r\n const installingWorker = registration.installing;\r\n installingWorker.onstatechange = () => {\r\n if (installingWorker.state === 'installed') {\r\n if (navigator.serviceWorker.controller) {\r\n // At this point, the old content will have been purged and\r\n // the fresh content will have been added to the cache.\r\n // It's the perfect time to display a \"New content is\r\n // available; please refresh.\" message in your web app.\r\n console.log('New content is available; please refresh.');\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 }\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) {\r\n // Check if the service worker can be found. If it can't reload the page.\r\n fetch(swUrl)\r\n .then(response => {\r\n // Ensure service worker exists, and that we really are getting a JS file.\r\n if (\r\n response.status === 404 ||\r\n response.headers.get('content-type').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);\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.then(registration => {\r\n registration.unregister();\r\n });\r\n }\r\n}\r\n","import { useState, useEffect, useCallback, useMemo } from 'react'\r\n\r\nconst initialState = {\r\n response: null,\r\n error: null,\r\n isLoading: true,\r\n}\r\n\r\nconst useFetch = (url, options, deps = [], predicate = true) => {\r\n const [state, setState] = useState(initialState)\r\n const [refreshCount, setRefreshCount] = useState(0)\r\n\r\n const refresh = useCallback(\r\n () => setRefreshCount((count) => count + 1), // will trigger useEffect to rerun\r\n []\r\n )\r\n\r\n const controller = useMemo(\r\n () => window.AbortController && new window.AbortController(),\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n [...deps, refreshCount] // recalculate a new controller if refresh initiated\r\n )\r\n const cancel = useCallback(() => controller && controller.abort(), [\r\n controller,\r\n ])\r\n\r\n useEffect(\r\n () => {\r\n const fetchData = async () => {\r\n setState({ ...state, isLoading: true })\r\n options.onStart && options.onStart()\r\n try {\r\n const res = await fetch(url, {\r\n ...options,\r\n signal: controller && controller.signal,\r\n })\r\n if (res.ok) {\r\n const json = await res.json()\r\n setState({\r\n response: json,\r\n isLoading: false,\r\n error: null,\r\n })\r\n options.onSuccess && options.onSuccess(json)\r\n } else {\r\n setState({\r\n response: null,\r\n error: res.statusText,\r\n isLoading: false,\r\n })\r\n options.onError && options.onError(res.statusText)\r\n }\r\n } catch (error) {\r\n setState({\r\n response: null,\r\n error,\r\n isLoading: false,\r\n })\r\n options.onError && options.onError(error)\r\n }\r\n }\r\n if (predicate) fetchData()\r\n else setState({ ...state, isLoading: false })\r\n return cancel\r\n },\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n [...deps, predicate, refreshCount] // only rerun when refreshcount is incremented\r\n )\r\n return [\r\n state,\r\n {\r\n refresh,\r\n cancel,\r\n },\r\n ]\r\n}\r\n\r\nexport default useFetch\r\n","import { useState, useEffect } from 'react'\r\nimport useFetch from './useFetch'\r\n\r\nconst useRecurrantFetch = (\r\n url,\r\n options,\r\n deps = [],\r\n predicate = true,\r\n refreshSeconds = 30,\r\n errorRefreshSeconds = 5\r\n) => {\r\n const [nextFetch, setNextFetch] = useState(\r\n new Date().getTime() + refreshSeconds * 1000\r\n )\r\n const [state, { refresh, cancel }] = useFetch(\r\n url,\r\n {\r\n ...options,\r\n onSuccess: (response) => {\r\n setNextFetch(new Date().getTime() + refreshSeconds * 1000)\r\n options.onSuccess && options.onSuccess(response)\r\n },\r\n onError: (error) => {\r\n setNextFetch(new Date().getTime() + errorRefreshSeconds * 1000)\r\n options.onError && options.onError(error)\r\n },\r\n },\r\n deps,\r\n predicate\r\n )\r\n\r\n useEffect(() => {\r\n if (nextFetch !== Infinity) {\r\n const waitTime = nextFetch - new Date().getTime()\r\n if (waitTime > 0) {\r\n const timeoutHandle = setTimeout(refresh, waitTime)\r\n return () => clearTimeout(timeoutHandle)\r\n } else {\r\n refresh()\r\n }\r\n }\r\n }, [nextFetch, refresh])\r\n\r\n return [\r\n state,\r\n {\r\n refresh: () => setNextFetch(0),\r\n cancel: () => {\r\n cancel()\r\n setNextFetch(Infinity)\r\n },\r\n },\r\n ]\r\n}\r\n\r\nexport default useRecurrantFetch\r\n","import { NAME } from './reducer'\r\n\r\nexport const getMap = (state) => state[NAME].map\r\nexport const getView = (state) => state[NAME].view\r\n","import { useState, useEffect, useCallback } from 'react'\r\nimport { useSelector, useDispatch } from 'react-redux'\r\n\r\nimport { getMap, getView } from './selectors'\r\nimport { setMapAndView } from './actions'\r\n\r\nconst initialState = {\r\n ready: false,\r\n classes: {},\r\n}\r\n\r\nconst getEsri1 = (deps) => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n window.esriRequire(deps, function () {\r\n const classes = Array.prototype.slice.call(arguments)\r\n let result = {}\r\n deps.forEach((fullClassName, index) => {\r\n const className = /[^/]*$/.exec(fullClassName)[0]\r\n result[className] = classes[index]\r\n })\r\n resolve(result)\r\n })\r\n } catch (exception) {\r\n console.error('require failed', exception)\r\n reject(exception)\r\n }\r\n })\r\n}\r\n\r\nfunction sleep(ms) {\r\n return new Promise((resolve) => setTimeout(resolve, ms))\r\n}\r\n\r\nconst getEsri = async (deps) => {\r\n if (typeof window.esriRequire !== 'function') {\r\n await sleep(100)\r\n return await getEsri(deps)\r\n }\r\n return await getEsri1(deps)\r\n}\r\n\r\nexport const useEsri = (dependencies) => {\r\n const [{ ready, classes }, setState] = useState(initialState)\r\n\r\n useEffect(() => {\r\n if (!ready) {\r\n getEsri(dependencies).then((classes) => {\r\n setState({\r\n ready: true,\r\n classes,\r\n })\r\n })\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [dependencies]) // only rerun if dependencies change\r\n\r\n return [ready, classes]\r\n}\r\n\r\nexport const useMap = () => {\r\n const dispatch = useDispatch()\r\n const map = useSelector(getMap)\r\n const view = useSelector(getView)\r\n\r\n const set = useCallback((map, view) => dispatch(setMapAndView(map, view)), [\r\n dispatch,\r\n ])\r\n\r\n return [{ map, view }, set]\r\n}\r\n","import { SET_MAP_AND_VIEW } from './actionTypes'\r\n\r\nexport const setMapAndView = (map, view) => ({\r\n type: SET_MAP_AND_VIEW,\r\n map,\r\n view,\r\n})\r\n","import * as ActionTypes from './actionTypes'\r\n\r\nexport const fetchSuccess = (closures) => ({\r\n type: ActionTypes.FETCH_SUCCESS,\r\n closures,\r\n})\r\n\r\nexport const fetchStart = () => ({\r\n type: ActionTypes.FETCH_START,\r\n})\r\n\r\nexport const fetchFail = (error) => ({\r\n type: ActionTypes.FETCH_FAILURE,\r\n error,\r\n})\r\n\r\nexport const selectClosures = (closureIds) => ({\r\n type: ActionTypes.SELECT_CLOSURES,\r\n closureIds,\r\n})\r\n\r\nexport const clearSelection = () => ({\r\n type: ActionTypes.CLEAR_SELECTION,\r\n})\r\n\r\nexport const hoverSegmentStart = (closureId, segmentId) => ({\r\n type: ActionTypes.HOVER_SEGMENT_START,\r\n closureId,\r\n segmentId,\r\n})\r\n\r\nexport const hoverSegmentEnd = (closureId, segmentId) => ({\r\n type: ActionTypes.HOVER_SEGMENT_END,\r\n closureId,\r\n segmentId,\r\n})\r\n","import { createSelector } from 'reselect'\r\n\r\nimport { NAME } from './reducer'\r\n\r\nconst byIdSelector = (state) => state[NAME].byId\r\nexport const getClosureIds = (state) => state[NAME].allKeys\r\n\r\nexport const getClosureById = createSelector([byIdSelector], (byId) => (id) =>\r\n byId[id] || null\r\n)\r\n\r\nexport const getClosures = createSelector(\r\n [getClosureById, getClosureIds],\r\n (byId, allKeys) => allKeys.map(byId)\r\n)\r\n\r\nexport const getClosuresIsLoading = (state) => state[NAME].roadClosuresIsLoading\r\n\r\nexport const getSelectedClosureIds = (state) => state[NAME].selected.closureIds\r\nexport const getCurrentSelectedIndex = (state) => state[NAME].selected.current\r\n\r\nconst getSelectedClosureId = createSelector(\r\n [getSelectedClosureIds, getCurrentSelectedIndex],\r\n (eventIds, current) => eventIds[current]\r\n)\r\n\r\nexport const getAllSelectedClosures = createSelector(\r\n [getSelectedClosureIds, getClosureById],\r\n (closureIds, byId) => closureIds.map(byId)\r\n)\r\n\r\nexport const getSelectedCount = createSelector(\r\n [getSelectedClosureIds],\r\n (selectedIds) => selectedIds.length\r\n)\r\n\r\nexport const getCurrentSelectedClosure = createSelector(\r\n [getSelectedClosureId, getClosureById],\r\n (closureId, byId) => byId(closureId)\r\n)\r\n","import { useMemo, useCallback } from 'react'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\nimport moment from 'moment'\r\n\r\nimport { BASE_URL } from '../constants'\r\n\r\nimport useRecurrantFetch from '../hooks/useRecurrantFetch'\r\n\r\nimport { useMap, useEsri } from '../map/hooks'\r\n\r\nimport {\r\n fetchSuccess,\r\n fetchStart,\r\n fetchFail,\r\n selectClosures,\r\n clearSelection,\r\n hoverSegmentStart,\r\n hoverSegmentEnd,\r\n} from './actions'\r\n\r\nimport {\r\n getClosureById,\r\n getClosures,\r\n getClosureIds,\r\n getClosuresIsLoading,\r\n getCurrentSelectedClosure,\r\n getSelectedClosureIds,\r\n getCurrentSelectedIndex,\r\n} from './selectors'\r\n\r\nexport const useRoadClosuresFetch = () => {\r\n const dispatch = useDispatch()\r\n\r\n return useRecurrantFetch(`${BASE_URL}api/roadClosures/active`, {\r\n onStart: () => dispatch(fetchStart()),\r\n onSuccess: (closures) => dispatch(fetchSuccess(closures)),\r\n onError: (error) => dispatch(fetchFail(error)),\r\n })\r\n}\r\n\r\nexport const useClosure = (closureId) => {\r\n const dispatch = useDispatch()\r\n const closure = useSelector(getClosureById)(closureId)\r\n\r\n const select = useCallback(() => dispatch(selectClosures([closureId])), [\r\n dispatch,\r\n closureId,\r\n ])\r\n\r\n return [closure, { select }]\r\n}\r\n\r\nexport const useSelectedClosure = () => useSelector(getCurrentSelectedClosure)\r\n\r\nexport const useSegmentList = () => {\r\n const [ready, { Polyline }] = useEsri(['esri/geometry/Polyline'])\r\n const closure = useSelectedClosure()\r\n const segments = closure.roadSegments || []\r\n\r\n const [{ view }] = useMap()\r\n const zoom = useCallback(\r\n (segment) => () => {\r\n ready && view && view.goTo({ target: new Polyline(segment.geometry) })\r\n },\r\n [view, ready, Polyline]\r\n )\r\n\r\n const dispatch = useDispatch()\r\n const actions = useMemo(\r\n () => ({\r\n onHover: (segmentId) => () =>\r\n dispatch(hoverSegmentStart(closure.id, segmentId)),\r\n onHoverEnd: (segmentId) => () =>\r\n dispatch(hoverSegmentEnd(closure.id, segmentId)),\r\n zoom,\r\n }),\r\n [dispatch, zoom, closure]\r\n )\r\n\r\n return [segments, actions]\r\n}\r\n\r\nexport const useClosures = () => {\r\n const closures = useSelector(getClosures)\r\n return closures\r\n}\r\n\r\nexport const useClosuresList = () => {\r\n const unsortedIds = useSelector(getClosureIds)\r\n const byId = useSelector(getClosureById)\r\n const isLoading = useSelector(getClosuresIsLoading)\r\n\r\n const sortFunc = (a, b) => {\r\n if (moment(a.closedDate).isSame(b.closedDate)) return a.id < b.id ? -1 : 1\r\n return moment(a.closedDate).isBefore(b.closedDate) ? 1 : -1\r\n }\r\n\r\n const closureIds = unsortedIds\r\n .map(byId)\r\n .sort(sortFunc)\r\n .map((e) => e.id)\r\n\r\n return [{ closureIds, isLoading }]\r\n}\r\n\r\nexport const useClosuresMap = () => {\r\n const dispatch = useDispatch()\r\n const selectedIds = useSelector(getSelectedClosureIds)\r\n const current = useSelector(getCurrentSelectedIndex)\r\n const closures = useSelector(getClosures)\r\n\r\n const select = useCallback(\r\n (closureIds) => dispatch(selectClosures(closureIds)),\r\n [dispatch]\r\n )\r\n const clear = useCallback(() => dispatch(clearSelection()), [dispatch])\r\n const selected = useMemo(() => ({ ids: selectedIds, current }), [\r\n selectedIds,\r\n current,\r\n ])\r\n return [\r\n { closures, selected },\r\n { select, clear },\r\n ]\r\n}\r\n","import React from 'react'\r\nimport { BASE_URL } from '../constants'\r\n\r\nimport styles from './BaseLayout.module.css'\r\n\r\nconst BaseLayout = ({ title, children }) => {\r\n return (\r\n
\r\n
\r\n \r\n

\r\n \r\n horrycounty.org\r\n {' '}\r\n - {title}\r\n

\r\n
\r\n {children}\r\n
\r\n )\r\n}\r\n\r\nexport default BaseLayout\r\n","import { useCallback } from 'react'\r\nimport { useLocation, useHistory } from 'react-router-dom'\r\nimport { matchPath } from 'react-router'\r\n\r\nexport const useSelectedTab = () => {\r\n const location = useLocation()\r\n return location.pathname\r\n}\r\n\r\nexport const useIsSelected = (path) => {\r\n const currentPath = useSelectedTab()\r\n const result = matchPath(currentPath, { path, isExact: true, strict: true })\r\n return result !== null && result.isExact\r\n}\r\n\r\nexport const useTab = (path) => {\r\n const history = useHistory()\r\n const isSelected = useIsSelected(path)\r\n\r\n const select = useCallback(() => {\r\n !isSelected && history.push(path)\r\n }, [path, history, isSelected])\r\n\r\n return [isSelected, select]\r\n}\r\n","import React from 'react'\r\n\r\nimport { useTab, useIsSelected } from '../hooks'\r\n\r\nimport styles from './Tabs.module.css'\r\n\r\nconst Tab = ({ path, label, icon, defaultPath }) => {\r\n const [iSelected, select] = useTab(path)\r\n const isDefaultPath = useIsSelected(defaultPath)\r\n\r\n return (\r\n \r\n {icon && }\r\n {label &&
{label}
}\r\n \r\n )\r\n}\r\nexport default Tab\r\n","import React from 'react'\r\n\r\nimport styles from './Tabs.module.css'\r\n\r\nconst TabMenu = ({ children }) => \r\nexport default TabMenu\r\n","import React from 'react'\r\nimport { Route } from 'react-router-dom'\r\n\r\nimport styles from './Tabs.module.css'\r\n\r\nconst TabPanel = ({ children, component: Component, ...rest }) => {\r\n return (\r\n \r\n
\r\n {Component && }\r\n {children}\r\n
\r\n
\r\n )\r\n}\r\n\r\nexport default TabPanel\r\n","import React from 'react'\r\nimport { Switch } from 'react-router-dom'\r\n\r\nconst TabPanelContainer = ({ children }) => {\r\n return {children}\r\n}\r\n\r\nexport default TabPanelContainer\r\n","import { useState, useEffect, useCallback, useMemo } from 'react'\r\n\r\nexport const useMedia = (query) => {\r\n const mediaQuery = useMemo(() => window.matchMedia(query), [query])\r\n const getResult = useCallback(() => mediaQuery.matches, [mediaQuery])\r\n const [result, setResult] = useState(getResult)\r\n\r\n useEffect(() => {\r\n const handler = () => setResult(getResult)\r\n mediaQuery.addListener(handler)\r\n return () => mediaQuery.removeListener(handler)\r\n }, [])\r\n return result\r\n}\r\n\r\nexport const useMedias = (queries, values, defaultValue) => {\r\n // Array containing a media query list for each query\r\n const mediaQueryLists = queries.map((q) => window.matchMedia(q))\r\n\r\n // Function that gets value based on matching media query\r\n const getValue = () => {\r\n // Get index of first media query that matches\r\n const index = mediaQueryLists.findIndex((mql) => mql.matches)\r\n // Return related value or defaultValue if none\r\n return typeof values[index] !== 'undefined' ? values[index] : defaultValue\r\n }\r\n\r\n // State and setter for matched value\r\n const [value, setValue] = useState(getValue)\r\n\r\n useEffect(\r\n () => {\r\n // Event listener callback\r\n // Note: By defining getValue outside of useEffect we ensure that it has ...\r\n // ... current values of hook args (as this hook callback is created once on mount).\r\n const handler = () => setValue(getValue)\r\n // Set a listener for each media query with above handler as callback.\r\n mediaQueryLists.forEach((mql) => mql.addListener(handler))\r\n // Remove listeners on cleanup\r\n return () => mediaQueryLists.forEach((mql) => mql.removeListener(handler))\r\n },\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n [] // Empty array ensures effect is only run on mount and unmount\r\n )\r\n\r\n return value\r\n}\r\n\r\nexport default useMedia\r\n","export const LOCATOR_URL =\r\n 'https://www.horrycounty.org/gisweb/rest/services/Locators/Composite_Locator/GeocodeServer'\r\n\r\nexport const ROADS_NAMELAYER_URL =\r\n 'https://www.horrycounty.org/gisweb/rest/services/Public/Streets/MapServer/0'\r\nexport const ROADS_LAYER_URL =\r\n 'https://www.horrycounty.org/gisweb/rest/services/Public/Streets/MapServer/1'\r\n\r\nexport const HORRY_STREETS_MAP =\r\n 'https://www.horrycounty.org/gisweb/rest/services/Public/Streets/MapServer'\r\nexport const HORRY_ELECTRIC_OUTAGES_LAYER =\r\n 'https://portal.horryelectric.com/gis_services/rest/services/Internal/OMS/MapServer'\r\n\r\nexport const PROXY_URL = 'https://www.horrycounty.org/apps/proxy/proxy.ashx'\r\n\r\nexport const TRAFFIC_LAYER_URL =\r\n 'https://traffic.arcgis.com/arcgis/rest/services/World/Traffic/MapServer'\r\n","import React, { useEffect } from 'react'\r\nimport { withRouter } from 'react-router-dom'\r\nimport { useEsri, useMap } from '../hooks'\r\n\r\nimport { useMedia } from '../../hooks/useMedia'\r\n\r\nimport { MOBILE_SCREEN_WIDTH } from '../../constants'\r\nimport { PROXY_URL } from '../constants'\r\n\r\nimport styles from './Map.module.css'\r\n\r\nconst esriReqs = ['esri/Map', 'esri/views/MapView', 'esri/core/urlUtils']\r\n\r\nconst Map = ({ children, basemap, padding }) => {\r\n const [ready, { Map, MapView, urlUtils }] = useEsri(esriReqs)\r\n const [{ map, view }, setMapAndView] = useMap()\r\n const isDesktop = useMedia(`(min-width: ${MOBILE_SCREEN_WIDTH}px)`)\r\n\r\n useEffect(() => {\r\n if (ready) {\r\n urlUtils.addProxyRule({\r\n urlPrefix: 'www.horrycounty.org/gisweb/',\r\n proxyUrl: PROXY_URL,\r\n })\r\n urlUtils.addProxyRule({\r\n urlPrefix: 'traffic.arcgis.com',\r\n proxyUrl: PROXY_URL,\r\n })\r\n\r\n const map = new Map({\r\n basemap: basemap || 'streets',\r\n })\r\n\r\n const viewOptions = {\r\n container: 'map',\r\n map: map,\r\n center: [-78.938501, 33.933995],\r\n zoom: 11,\r\n }\r\n\r\n if (padding) {\r\n viewOptions.ui = {\r\n padding,\r\n }\r\n }\r\n\r\n const view = new MapView(viewOptions)\r\n\r\n if (isDesktop) {\r\n view.popup.dockOptions.position = 'bottom-right'\r\n view.popup.actions.removeAll()\r\n } else {\r\n view.popup = null\r\n }\r\n\r\n setMapAndView(map, view)\r\n }\r\n }, [\r\n ready,\r\n Map,\r\n MapView,\r\n urlUtils,\r\n basemap,\r\n padding,\r\n setMapAndView,\r\n isDesktop,\r\n ])\r\n\r\n const kids = React.Children.map(children, (child) => {\r\n return React.cloneElement(child, { map, view })\r\n })\r\n\r\n return (\r\n
\r\n {view && map && kids}\r\n
\r\n )\r\n}\r\n\r\nexport default withRouter(Map)\r\n","import { useEffect } from 'react'\r\n\r\nconst Zoom = ({ map, view, position }) => {\r\n useEffect(() => {\r\n if (map && view) {\r\n if (position === 'none') {\r\n view.ui.remove('zoom')\r\n } else {\r\n view.ui.move('zoom', position || 'bottom-right')\r\n }\r\n }\r\n }, [map, view, position])\r\n\r\n return null\r\n}\r\n\r\nexport default Zoom\r\n","import { useEffect } from 'react'\r\nimport { useEsri } from '../hooks'\r\n\r\nconst esriReqs = ['esri/widgets/BasemapToggle']\r\n\r\nconst Toggle = ({ map, view, position, next }) => {\r\n const [ready, { BasemapToggle }] = useEsri(esriReqs)\r\n\r\n useEffect(() => {\r\n if (ready && map && view) {\r\n const basemapToggle = new BasemapToggle({\r\n view,\r\n nextBasemap: next || 'satellite'\r\n })\r\n view.ui.add(basemapToggle, position || 'top-right')\r\n }\r\n }, [ready, BasemapToggle, map, view, position, next])\r\n\r\n return null\r\n}\r\n\r\nexport default Toggle\r\n","import { useEffect } from 'react'\r\nimport { useEsri } from '../hooks'\r\n\r\nconst esriReqs = ['esri/widgets/Compass']\r\n\r\nconst CompassWidget = ({ map, view, position }) => {\r\n const [ready, { Compass }] = useEsri(esriReqs)\r\n\r\n useEffect(() => {\r\n if (ready && map && view) {\r\n const compass = new Compass({\r\n view\r\n })\r\n view.ui.add(compass, position || 'top-right')\r\n }\r\n }, [ready, Compass, map, view, position])\r\n\r\n return null\r\n}\r\n\r\nexport default CompassWidget\r\n","import { useEffect, useState } from 'react'\r\nimport { useEsri } from '../hooks'\r\n\r\nconst esriReqs = ['esri/Graphic', 'esri/layers/GraphicsLayer']\r\n\r\nconst GraphicLayer = ({\r\n id,\r\n map,\r\n view,\r\n graphics,\r\n onSelect,\r\n onDeselect,\r\n onClick,\r\n}) => {\r\n const [ready, { Graphic, GraphicsLayer }] = useEsri(esriReqs)\r\n const [layer, setLayer] = useState(null)\r\n const [layerId] = useState(id || '')\r\n\r\n useEffect(() => {\r\n if (ready && map) {\r\n const newLayer = new GraphicsLayer()\r\n map.add(newLayer)\r\n setLayer(newLayer)\r\n }\r\n }, [ready, GraphicsLayer, map])\r\n\r\n // Refresh graphics when data changes\r\n useEffect(() => {\r\n if (layer && Graphic && graphics) {\r\n const newGraphics = graphics.map(\r\n (graphic) =>\r\n new Graphic({\r\n geometry: graphic.geometry,\r\n symbol: graphic.symbol,\r\n attributes: {\r\n data: graphic,\r\n layerId,\r\n },\r\n })\r\n )\r\n layer.removeAll()\r\n layer.addMany(newGraphics)\r\n }\r\n }, [layer, Graphic, layerId, graphics])\r\n\r\n // Set on click handler for layer\r\n useEffect(() => {\r\n if (view) {\r\n const handler = view.on('click', (event) => {\r\n const screenPoint = {\r\n x: event.x,\r\n y: event.y,\r\n }\r\n\r\n onClick && onClick(event.mapPoint.longitude, event.mapPoint.latitude)\r\n\r\n view.hitTest(screenPoint).then((response) => {\r\n // Select data when you click on a graphic\r\n if (response.results.length) {\r\n const matching = response.results.filter(\r\n (result) =>\r\n result &&\r\n result.graphic &&\r\n result.graphic.attributes &&\r\n result.graphic.attributes.layerId === layerId\r\n )\r\n if (matching.length) {\r\n onSelect &&\r\n onSelect(\r\n matching.map((result) => result.graphic.attributes.data)\r\n )\r\n }\r\n } else {\r\n // Or deselect data when you click elsewhere\r\n onDeselect && onDeselect()\r\n }\r\n })\r\n })\r\n return handler.remove\r\n }\r\n }, [view, onSelect, onDeselect, onClick, layerId])\r\n\r\n return null\r\n}\r\n\r\nexport default GraphicLayer\r\n","import React, { useCallback, useMemo, useEffect } from 'react'\r\n\r\nimport { useClosuresMap } from '../../roadClosures/hooks'\r\nimport { useEsri } from '../hooks'\r\n\r\nimport GraphicLayer from './GraphicLayer'\r\n\r\nconst getSegmentSymbol = (isHovered, isSelected) => {\r\n return isHovered\r\n ? {\r\n type: 'simple-line', // autocasts as new SimpleLineSymbol()\r\n color: 'green',\r\n width: '3px',\r\n style: 'solid',\r\n }\r\n : isSelected\r\n ? {\r\n type: 'simple-line', // autocasts as new SimpleLineSymbol()\r\n color: 'red', //'blue',\r\n width: '3px',\r\n style: 'solid',\r\n }\r\n : {\r\n type: 'simple-line', // autocasts as new SimpleLineSymbol()\r\n color: 'red',\r\n width: '2px',\r\n style: 'solid',\r\n }\r\n}\r\n\r\nconst getSegmentGeometry = (segment) => ({\r\n type: 'polyline',\r\n paths: segment.geometry.paths,\r\n})\r\n\r\nconst getSegmentAttributes = (closure) => ({\r\n id: closure.id,\r\n})\r\n\r\nconst RoadClosuresLayer = ({ map, view }) => {\r\n const [ready, { Polyline }] = useEsri(['esri/geometry/Polyline'])\r\n const [\r\n { closures, selected, editorIsOpen },\r\n { select, clear },\r\n ] = useClosuresMap()\r\n\r\n const getIsSelected = useCallback(\r\n (graphic) =>\r\n selected.ids.length &&\r\n selected.ids[selected.current] === graphic.attributes.id,\r\n [selected]\r\n )\r\n\r\n const graphics = useMemo(\r\n () =>\r\n editorIsOpen\r\n ? []\r\n : closures.flatMap((closure) => {\r\n const isSelected =\r\n selected.ids.length &&\r\n selected.ids[selected.current] === closure.id\r\n return closure.roadSegments.map((segment) => ({\r\n geometry: getSegmentGeometry(segment),\r\n symbol: getSegmentSymbol(segment.hover, isSelected),\r\n attributes: getSegmentAttributes(closure),\r\n }))\r\n }),\r\n [closures, selected, editorIsOpen]\r\n )\r\n\r\n const onSelect = useCallback(\r\n (graphics) => {\r\n if (editorIsOpen) return\r\n if (\r\n !selected.ids.some((id) => graphics.some((g) => g.attributes.id === id))\r\n ) {\r\n select(graphics.map((g) => g.attributes.id))\r\n }\r\n },\r\n [select, selected, editorIsOpen]\r\n )\r\n\r\n const onDeselect = useCallback(() => {\r\n if (editorIsOpen) return\r\n clear()\r\n }, [editorIsOpen, clear])\r\n\r\n // Zoom/pan on selection change\r\n useEffect(() => {\r\n if (ready && Polyline && selected.ids.length) {\r\n const id = selected.ids[selected.current]\r\n const graphic = graphics.find((g) => g.attributes.id === id)\r\n console.log('graphic', graphic)\r\n if (graphic && graphic.geometry) {\r\n view.goTo(new Polyline(graphic.geometry))\r\n }\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [selected, view, ready, Polyline]) // only update when selection changes\r\n\r\n return (\r\n \r\n )\r\n}\r\n\r\nexport default RoadClosuresLayer\r\n","import * as ActionTypes from './actionTypes'\r\n\r\nexport const fetchSuccess = (results) => ({\r\n type: ActionTypes.FETCH_SUCCESS,\r\n results,\r\n})\r\n\r\nexport const fetchStart = () => ({\r\n type: ActionTypes.FETCH_START,\r\n})\r\n\r\nexport const fetchFail = (error) => ({\r\n type: ActionTypes.FETCH_FAILURE,\r\n error,\r\n})\r\n\r\nexport const selectResults = (resultIds) => ({\r\n type: ActionTypes.SELECT_RESULTS,\r\n resultIds,\r\n})\r\n\r\nexport const clearSelection = () => ({\r\n type: ActionTypes.CLEAR_SELECTION,\r\n})\r\n\r\nexport const hoverResultStart = (resultId) => ({\r\n type: ActionTypes.HOVER_RESULT_START,\r\n resultId,\r\n})\r\n\r\nexport const hoverResultEnd = (resultId) => ({\r\n type: ActionTypes.HOVER_RESULT_END,\r\n resultId,\r\n})\r\n","import { createSelector } from 'reselect'\r\n\r\nimport { NAME } from './reducer'\r\n\r\nconst byIdSelector = (state) => state[NAME].byId\r\nexport const getResultIds = (state) => state[NAME].allKeys\r\n\r\nexport const getResultById = createSelector([byIdSelector], (byId) => (id) =>\r\n byId[id] || null\r\n)\r\n\r\nexport const getResults = createSelector(\r\n [getResultById, getResultIds],\r\n (byId, allKeys) => allKeys.map(byId)\r\n)\r\n\r\nexport const getResultsIsLoading = (state) => state[NAME].resultsIsLoading\r\n\r\nexport const getSelectedResultIds = (state) => state[NAME].selected.resultIds\r\nexport const getCurrentSelectedIndex = (state) => state[NAME].selected.current\r\n\r\nconst getSelectedResultId = createSelector(\r\n [getSelectedResultIds, getCurrentSelectedIndex],\r\n (eventIds, current) => eventIds[current]\r\n)\r\n\r\nexport const getAllSelectedResults = createSelector(\r\n [getSelectedResultIds, getResultById],\r\n (resultIds, byId) => resultIds.map(byId)\r\n)\r\n\r\nexport const getSelectedCount = createSelector(\r\n [getSelectedResultIds],\r\n (selectedIds) => selectedIds.length\r\n)\r\n\r\nexport const getCurrentSelectedResult = createSelector(\r\n [getSelectedResultId, getResultById],\r\n (resultId, byId) => byId(resultId)\r\n)\r\n","import React, { useCallback, useMemo, useEffect } from 'react'\r\n\r\nimport { useResultsMap } from '../../search/hooks'\r\nimport { BASE_URL } from '../../constants'\r\nimport { useEsri } from '../hooks'\r\n\r\nimport GraphicLayer from './GraphicLayer'\r\n\r\nconst getResultSymbol = (isHovered, isSelected) => {\r\n return isHovered\r\n ? {\r\n type: 'picture-marker', // autocasts as new SimpleLineSymbol()\r\n url: `${BASE_URL}images/icons/pinFlagSelected.png`,\r\n width: '32px',\r\n height: '48px',\r\n yoffset: 24,\r\n }\r\n : isSelected\r\n ? {\r\n type: 'picture-marker', // autocasts as new SimpleLineSymbol()\r\n url: `${BASE_URL}images/icons/pinFlagSelected.png`,\r\n width: '32px',\r\n height: '48px',\r\n yoffset: 24,\r\n }\r\n : {\r\n type: 'picture-marker', // autocasts as new SimpleLineSymbol()\r\n url: `${BASE_URL}images/icons/pinFlag.png`,\r\n width: '32px',\r\n height: '48px',\r\n yoffset: 24,\r\n }\r\n}\r\n\r\nconst getResultGeometry = (result) => ({\r\n type: 'point',\r\n x: result.location.longitude,\r\n y: result.location.latitude,\r\n})\r\n\r\nconst getResultAttributes = (result) => ({\r\n id: result.id,\r\n})\r\n\r\nconst AddressSearchLayer = ({ map, view }) => {\r\n const [{ results, selected }, { select, clear }] = useResultsMap()\r\n\r\n const getIsSelected = useCallback(\r\n (graphic) =>\r\n selected.ids.length &&\r\n selected.ids[selected.current] === graphic.attributes.id,\r\n [selected]\r\n )\r\n\r\n const graphics = useMemo(\r\n () =>\r\n results.flatMap((result) => {\r\n const isSelected =\r\n selected.ids.length && selected.ids[selected.current] === result.id\r\n return {\r\n geometry: getResultGeometry(result),\r\n symbol: getResultSymbol(false, isSelected),\r\n attributes: getResultAttributes(result),\r\n }\r\n }),\r\n [results, selected]\r\n )\r\n\r\n const onSelect = useCallback(\r\n (graphics) => {\r\n if (\r\n !selected.ids.some((id) => graphics.some((g) => g.attributes.id === id))\r\n ) {\r\n select(graphics.map((g) => g.attributes.id))\r\n }\r\n },\r\n [select, selected]\r\n )\r\n\r\n const onDeselect = useCallback(() => {\r\n clear()\r\n }, [clear])\r\n\r\n // Zoom/pan on selection change\r\n useEffect(() => {\r\n if (selected.ids.length) {\r\n const id = selected.ids[selected.current]\r\n const graphic = graphics.find((g) => g.attributes.id === id)\r\n if (graphic && graphic.geometry) {\r\n view.goTo({\r\n center: [graphic.geometry.x, graphic.geometry.y],\r\n zoom: 15,\r\n })\r\n }\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [selected, view]) // only update when selection changes\r\n\r\n return (\r\n \r\n )\r\n}\r\n\r\nexport default AddressSearchLayer\r\n","import { useMemo, useCallback, useState } from 'react'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\nimport moment from 'moment'\r\n\r\nimport { BASE_URL } from '../constants'\r\n\r\nimport useRecurrantFetch from '../hooks/useRecurrantFetch'\r\n\r\nimport {\r\n fetchSuccess,\r\n fetchStart,\r\n fetchFail,\r\n selectResults,\r\n clearSelection,\r\n hoverResultStart,\r\n hoverResultEnd,\r\n} from './actions'\r\n\r\nimport {\r\n getResultById,\r\n getResults,\r\n getResultIds,\r\n getResultsIsLoading,\r\n getSelectedResultIds,\r\n getCurrentSelectedIndex,\r\n} from './selectors'\r\n\r\nexport const useAddressSearch = () => {\r\n const dispatch = useDispatch()\r\n const [query, setQuery] = useState('')\r\n\r\n const search = useCallback(async () => {\r\n dispatch(fetchStart())\r\n try {\r\n const response = await fetch(`${BASE_URL}api/address/search`, {\r\n method: 'POST',\r\n headers: {\r\n ['Content-Type']: 'application/json',\r\n },\r\n body: JSON.stringify({\r\n query,\r\n }),\r\n })\r\n if (response.ok) {\r\n const results = await response.json()\r\n console.log('results', results)\r\n dispatch(fetchSuccess(results))\r\n } else {\r\n dispatch(fetchFail(response.error))\r\n }\r\n } catch (e) {\r\n dispatch(fetchFail(e))\r\n }\r\n }, [dispatch, query])\r\n\r\n return [query, { search, setQuery }]\r\n}\r\n\r\nexport const useResult = (resultId) => {\r\n const dispatch = useDispatch()\r\n const result = useSelector(getResultById)(resultId)\r\n\r\n const select = useCallback(() => dispatch(selectResults([resultId])), [\r\n dispatch,\r\n resultId,\r\n ])\r\n\r\n return [result, { select }]\r\n}\r\n\r\nexport const useResults = () => {\r\n const results = useSelector(getResults)\r\n return results\r\n}\r\n\r\nexport const useResultsList = () => {\r\n const unsortedIds = useSelector(getResultIds)\r\n const byId = useSelector(getResultById)\r\n const isLoading = useSelector(getResultsIsLoading)\r\n\r\n const sortFunc = (a, b) => {\r\n return a.score > b.score ? -1 : 1\r\n }\r\n\r\n const resultIds = unsortedIds\r\n .map(byId)\r\n .sort(sortFunc)\r\n .map((e) => e.id)\r\n\r\n return [{ resultIds, isLoading }]\r\n}\r\n\r\nexport const useResultsMap = () => {\r\n const dispatch = useDispatch()\r\n const selectedIds = useSelector(getSelectedResultIds)\r\n const current = useSelector(getCurrentSelectedIndex)\r\n const results = useSelector(getResults)\r\n\r\n const select = useCallback(\r\n (resultIds) => dispatch(selectResults(resultIds)),\r\n [dispatch]\r\n )\r\n const clear = useCallback(() => dispatch(clearSelection()), [dispatch])\r\n const selected = useMemo(() => ({ ids: selectedIds, current }), [\r\n selectedIds,\r\n current,\r\n ])\r\n return [\r\n { results, selected },\r\n { select, clear },\r\n ]\r\n}\r\n","import React from 'react'\r\n\r\nimport styles from './Header.module.css'\r\n\r\nconst Header = ({ children }) => {\r\n return

{children}

\r\n}\r\n\r\nexport default Header\r\n","import React from 'react'\r\nimport moment from 'moment'\r\n\r\nconst FormattedDate = ({ style, date, children }) => {\r\n const formattedDate = moment(\r\n moment.utc(date).format('YYYY-MM-DD HH:mm')\r\n ).fromNow()\r\n //moment.utc(date).format('M/D/YYYY h:mmA')\r\n\r\n return (\r\n
\r\n {children} {formattedDate}\r\n
\r\n )\r\n}\r\n\r\nexport default FormattedDate\r\n","import React, { useMemo } from 'react'\r\n\r\nimport { BASE_URL } from '../../constants'\r\n\r\nimport { useClosure } from '../hooks'\r\n\r\nimport FormattedDate from '../../common/FormattedDate'\r\n\r\nimport styles from './ClosureListItem.module.css'\r\n\r\nconst getIconFromReason = (reason) => {\r\n switch (reason) {\r\n case 'Construction':\r\n return 'RoadClosures_Construction.png'\r\n case 'Flood':\r\n return 'RoadClosures_Flood.png'\r\n case 'Washout':\r\n return 'RoadClosures_Washout.png'\r\n case 'Snow/Ice':\r\n return 'RoadClosures_Snow.png'\r\n case 'Debris':\r\n return 'RoadClosures_Debris.png'\r\n case 'Emergency':\r\n return 'RoadClosures_Emergency.png'\r\n case 'Other':\r\n return 'RoadClosures_Other.png'\r\n default:\r\n return 'question.png'\r\n }\r\n}\r\n\r\nconst ClosureListItem = ({ closureId }) => {\r\n const [{ closedDate, reason, roadSegments }, { select }] = useClosure(\r\n closureId\r\n )\r\n\r\n const label = useMemo(() => {\r\n const roadNames = []\r\n roadSegments.forEach((segment) => {\r\n if (!roadNames.includes(segment.name)) roadNames.push(segment.name)\r\n })\r\n return roadNames.join(', ')\r\n }, [roadSegments])\r\n\r\n return (\r\n
  • \r\n \r\n
    {label}
    \r\n \r\n Closed -{' '}\r\n \r\n
  • \r\n )\r\n}\r\nexport default ClosureListItem\r\n","import React from 'react'\r\n\r\nimport { useClosuresList } from '../hooks'\r\n\r\nimport Header from '../../common/Header'\r\nimport ClosureListItem from './ClosureListItem'\r\n\r\nimport styles from './ClosureList.module.css'\r\n\r\nconst ClosureList = () => {\r\n const [{ closureIds, isLoading }] = useClosuresList()\r\n\r\n return (\r\n
    \r\n
    \r\n {closureIds.length} Closures{' '}\r\n {isLoading && }\r\n
    \r\n
      \r\n {closureIds.map((closureId, i) => (\r\n \r\n ))}\r\n
    \r\n
    \r\n )\r\n}\r\n\r\nexport default ClosureList\r\n","import React, { useCallback } from 'react'\r\n\r\nimport styles from './Input.module.css'\r\n\r\nconst TextInput = ({\r\n type,\r\n value,\r\n onChange,\r\n placeholder,\r\n label,\r\n disabled,\r\n className,\r\n button,\r\n ...rest\r\n}) => {\r\n const onKeyPressed = useCallback(\r\n (e) => {\r\n if (e.key === 'Enter') {\r\n button && button.onClick()\r\n }\r\n },\r\n [button]\r\n )\r\n\r\n return (\r\n \r\n onChange(e.target.value)}\r\n onKeyPress={onKeyPressed}\r\n disabled={disabled}\r\n required\r\n {...rest}\r\n />\r\n \r\n {button && (\r\n \r\n )}\r\n \r\n )\r\n}\r\n\r\nexport default TextInput\r\n","import React from 'react'\r\n\r\nimport { useResult } from '../hooks'\r\n\r\nimport styles from './SearchResult.module.css'\r\n\r\nconst SearchResult = ({ resultId }) => {\r\n const [result, { select }] = useResult(resultId)\r\n\r\n return (\r\n
  • \r\n {result.address}\r\n
  • \r\n )\r\n // return (\r\n //
  • \r\n // \r\n //
    {label}
    \r\n //
  • \r\n // )\r\n}\r\nexport default SearchResult\r\n","import React from 'react'\r\n\r\nimport { useAddressSearch, useResultsList } from '../hooks'\r\n\r\nimport Header from '../../common/Header'\r\nimport TextInput from '../../common/TextInput'\r\n\r\nimport SearchResult from './SearchResult'\r\n\r\nimport styles from './SearchPanel.module.css'\r\n\r\nconst SearchPanel = () => {\r\n const [query, { search, setQuery }] = useAddressSearch()\r\n const [{ resultIds, isLoading }] = useResultsList()\r\n\r\n return (\r\n
    \r\n
    \r\n Search {isLoading && }\r\n
    \r\n \r\n {resultIds &&\r\n (resultIds.length ? (\r\n
      \r\n {resultIds.map((resultId, i) => (\r\n \r\n ))}\r\n
    \r\n ) : (\r\n
    No Results
    \r\n ))}\r\n
    \r\n )\r\n}\r\n\r\nexport default SearchPanel\r\n","import React, { useMemo } from 'react'\r\n\r\nimport { useRoadClosuresFetch } from './roadClosures/hooks'\r\n\r\nimport BaseLayout from './common/BaseLayout'\r\n\r\nimport Tab from './tabs/components/Tab'\r\nimport TabMenu from './tabs/components/TabMenu'\r\nimport TabPanel from './tabs/components/TabPanel'\r\nimport TabPanelContainer from './tabs/components/TabPanelContainer'\r\n\r\nimport Map from './map/components/Map'\r\nimport Zoom from './map/components/Zoom'\r\nimport BasemapToggle from './map/components/BasemapToggle'\r\nimport Compass from './map/components/Compass'\r\nimport RoadClosuresLayer from './map/components/RoadClosuresLayer'\r\nimport AddressSearchLayer from './map/components/AddressSearchLayer'\r\n\r\nimport ClosureList from './roadClosures/components/ClosureList'\r\nimport SearchPanel from './search/components/SearchPanel'\r\n\r\nimport styles from './App.module.css'\r\n\r\nconst App = () => {\r\n useRoadClosuresFetch()\r\n\r\n const mapPadding = useMemo(\r\n () => ({\r\n top: 60,\r\n left: 460,\r\n right: 10,\r\n bottom: 20,\r\n }),\r\n []\r\n )\r\n\r\n return (\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\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","import 'react-app-polyfill/ie9'\r\nimport React from 'react'\r\nimport ReactDOM from 'react-dom'\r\nimport { Provider } from 'react-redux'\r\nimport { BrowserRouter as Router } from 'react-router-dom'\r\nimport { BASE_URL } from './constants'\r\n\r\nimport configureStore from './store'\r\n\r\nimport registerServiceWorker from './registerServiceWorker'\r\n\r\nimport './index.css'\r\nimport App from './App'\r\n\r\nimport Bugsnag from '@bugsnag/js'\r\nimport BugsnagPluginReact from '@bugsnag/plugin-react'\r\n\r\nBugsnag.start({\r\n apiKey: 'cd716d7579557a0753ffd1e5228e0cd0',\r\n plugins: [new BugsnagPluginReact()],\r\n})\r\nconst ErrorBoundary = Bugsnag.getPlugin('react').createErrorBoundary(React)\r\n\r\nconst initialState = window.initialReduxState || {}\r\nconst store = configureStore(initialState)\r\n\r\nReactDOM.render(\r\n \r\n \r\n \r\n \r\n \r\n \r\n ,\r\n document.getElementById('root')\r\n)\r\nregisterServiceWorker()\r\n","import { applyMiddleware, combineReducers, compose, createStore } from 'redux'\r\nimport thunk from 'redux-thunk'\r\n\r\nimport RoadClosuresReducer, {\r\n NAME as RoadClosuresReducerName,\r\n} from './roadClosures/reducer'\r\nimport SearchReducer, { NAME as SearchReducerName } from './search/reducer'\r\nimport MapReducer, { NAME as MapReducerName } from './map/reducer'\r\n\r\nexport default function configureStore(initialState) {\r\n const reducers = {\r\n [RoadClosuresReducerName]: RoadClosuresReducer,\r\n [MapReducerName]: MapReducer,\r\n [SearchReducerName]: SearchReducer,\r\n }\r\n\r\n const middleware = [thunk]\r\n\r\n // In development, use the browser's Redux dev tools extension if installed\r\n const enhancers = []\r\n const isDevelopment = process.env.NODE_ENV === 'development'\r\n if (\r\n isDevelopment &&\r\n typeof window !== 'undefined' &&\r\n window.devToolsExtension\r\n ) {\r\n enhancers.push(window.devToolsExtension())\r\n }\r\n\r\n const rootReducer = combineReducers({\r\n ...reducers,\r\n })\r\n\r\n return createStore(\r\n rootReducer,\r\n initialState,\r\n compose(applyMiddleware(...middleware), ...enhancers)\r\n )\r\n}\r\n","// extracted by mini-css-extract-plugin\nmodule.exports = {\"tabPanel\":\"Tabs_tabPanel__eqAQi\",\"tabMenu\":\"Tabs_tabMenu__9Q69t\",\"tab\":\"Tabs_tab__c99pg\",\"tabSelected\":\"Tabs_tabSelected__3-OGk Tabs_tab__c99pg\",\"tabLabel\":\"Tabs_tabLabel__2hyCA\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"container\":\"BaseLayout_container__2c5Gf\",\"logo\":\"BaseLayout_logo__jiGWH\",\"headerTitleLink\":\"BaseLayout_headerTitleLink__1FH_l\",\"header\":\"BaseLayout_header__1mjdw\",\"headerTitle\":\"BaseLayout_headerTitle__RWvfZ\",\"layoutBody\":\"BaseLayout_layoutBody__3P_Kj\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"defaultContainer\":\"Input_defaultContainer__1X28j\",\"container\":\"Input_container__eAUIH\",\"input\":\"Input_input__1_zon\",\"inputWithButton\":\"Input_inputWithButton__34c2r\",\"inputButton\":\"Input_inputButton__1OxCv\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"item\":\"ClosureListItem_item__2_Y2Y\",\"icon\":\"ClosureListItem_icon__2D_E4\",\"title\":\"ClosureListItem_title__1HVoU\",\"timestamp\":\"ClosureListItem_timestamp__2ubnv\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"container\":\"SearchPanel_container__1t1Nr\",\"list\":\"SearchPanel_list__6ur2h\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"tabBar\":\"App_tabBar__2zw1L\",\"sideBar\":\"App_sideBar__2rgfS\",\"headerMenu\":\"App_headerMenu__3h7sT\"};"],"sourceRoot":""}