diff --git a/components/FilterPanel/index.js b/components/FilterPanel/index.js index 9e24e5b..eab5606 100644 --- a/components/FilterPanel/index.js +++ b/components/FilterPanel/index.js @@ -31,14 +31,8 @@ const filters = [ { name: 'Travel', icon: abroad, add: addTravel, remove: removeTravel }, ] -//{ name: 'Travel', icon: abroad, add: addTravel, remove: removeTravel }, - const HeaderContainer = styled.div` - padding-top: 10px; - background-color: #f2f2f2; - display: grid; - grid-template-rows: 7% 93%; - overflow: auto; + margin: 30px 0px; font-family: 'Lato', sans-serif; color: #7c7a7a; font-weight: bold; @@ -51,9 +45,6 @@ const HeaderContainer = styled.div` ` const FilterMenuContainer = styled.div` - display: grid; - grid-template-rows: 10% 10% 10% 10% 60%; - overflow: auto; font-family: 'Lato', sans-serif; color: #7c7a7a; font-weight: bold; @@ -64,30 +55,31 @@ const FilterMenuContainer = styled.div` } ` -const FilterCategory = ({ filter, onClick, selected }) => { - const FilterContainer = styled.div` - display: flex; - flex-direction: column; - align-items: center; - justify-content: space-evenly; - height: '20vh'; - user-select: none; - background-color: ${props => (props.selected ? '#d6d6d6' : '#F2F2F2')}; - transition: all 0.2s ease-out; - cursor: pointer; - &:hover { - background-color: #d7d7d7; - } - ` - const FilterName = styled.div` - text-transform: uppercase; - font-size: 11px; - ` - - const FilterIcon = styled.img` - width: 40px; - ` +const FilterContainer = styled.div` + padding: 5px 0px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-evenly; + height: '20vh'; + background-color: ${props => (props.selected ? '#d7d7d7' : 'transparent')}; + transition: all 0.2s ease-out; + cursor: pointer; + &:hover { + background-color: #d7d7d7; + } +` + +const FilterName = styled.div` + text-transform: uppercase; + font-size: 11px; +` + +const FilterIcon = styled.img` + width: 40px; +` +const FilterCategory = ({ filter, onClick, selected }) => { return ( @@ -122,20 +114,9 @@ const FilterPanel = ({ console.log(newGraph) updateGraph(newGraph) } - const FilterHeader = styled.div` - text-align: center; - text-transform: uppercase; - font-size: 14px; - - @media screen and (max-width: 768px) { - display: flex; - align-items: center; - justify-content: center; - } - ` + return ( - Cluster Filter {filters.map((filterItem, filterIndex) => ( diff --git a/components/Loader.js b/components/Loader.js new file mode 100644 index 0000000..d63a3b7 --- /dev/null +++ b/components/Loader.js @@ -0,0 +1,132 @@ +import React from 'react' +import styled, { keyframes } from 'styled-components' + +const rotateBall = props => keyframes` + ${(((props.size / 2 / props.countBalls) * (props.index - 1)) / props.size) * + 100}% { + opacity: 0; + } + ${(((props.size / 2 / props.countBalls + 0.0001) * (props.index - 1)) / + props.size) * + 100}% { + opacity: 1; + transform: ${`rotate(${0 - + (360 / props.countBalls) * (props.index - 2)}deg)`}; + } + ${(((props.size / 2 / props.countBalls) * (props.index - 0) + 2) / + props.size) * + 100}% { + transform: ${`rotate(${0 - + (360 / props.countBalls) * (props.index - 1)}deg)`}; + } + ${((props.size / 2 + + (props.size / 2 / props.countBalls) * (props.index - 0) + + 2) / + props.size) * + 100}% { + transform: ${`rotate(${0 - + (360 / props.countBalls) * (props.index - 1)}deg)`}; + } + 100% { + transform: ${`rotate(${0 - + (360 / props.countBalls) * (props.countBalls - 1)}deg)`}; + opacity: 1; + } +` + +const getBalls = ({ + countBalls, + radius, + angle, + color, + size, + ballSize, + sizeUnit, +}) => { + const balls = [] + const offset = ballSize / 2 + for (let i = 0; i < countBalls; i++) { + const y = Math.sin(angle * i * (Math.PI / 180)) * radius - offset + const x = Math.cos(angle * i * (Math.PI / 180)) * radius - offset + balls.push( + + ) + } + return balls +} + +const rotate = keyframes` + 0% { + transform: rotate(0deg); + } + 100%{ + transform: rotate(-360deg); + } +` + +const Wrapper = styled.div` + left: 20px; + position: fixed; + justify-content: center; + align-items: center; + width: ${props => `${props.size}${props.sizeUnit}`}; + height: ${props => `${props.size}${props.sizeUnit}`}; + animation: ${rotate} 3s infinite ease-in; +` + +const Ball = styled.div` + position: absolute; + width: ${props => `${props.size}${props.sizeUnit}`}; + height: ${props => `${props.size}${props.sizeUnit}`}; + animation: ${rotateBall} 2s infinite linear; + transform: ${props => `rotate(${(360 / props.countBalls) * props.index}deg)`}; + opacity: 0; + &:before { + content: ''; + position: absolute; + left: 50%; + top: 0%; + width: ${props => `${props.ballSize}${props.sizeUnit}`}; + height: ${props => `${props.ballSize}${props.sizeUnit}`}; + background-color: ${props => `${props.color}`}; + transform: translateX(-50%); + border-radius: 50%; + } +` + +export default function Loader({ + size = 30, + color = '#201AA2', + loading = true, + sizeUnit = 'px', +}) { + const radius = size / 2 + const countBalls = 9 + const ballSize = size / 8 + const angle = 360 / countBalls + return ( + loading && ( + + {getBalls({ + countBalls, + radius, + angle, + color, + size, + ballSize, + sizeUnit, + })} + + ) + ) +} diff --git a/components/NetworkMap/index.js b/components/NetworkMap/index.js index 5a77c21..d873e29 100644 --- a/components/NetworkMap/index.js +++ b/components/NetworkMap/index.js @@ -2,7 +2,16 @@ import React, { useState, useEffect, useRef, useMemo } from 'react' import Graph from 'react-graph-vis' import { Tooltip, TooltipArrow, TooltipInner } from 'styled-tooltip-component' import { connect, useSelector } from 'react-redux' -import { updateGraph, updatePatients, updateLastRefreshed, selectPatient, updateStates } from '../Redux/actions' +import { + updateGraph, + updatePatients, + updateLastRefreshed, + selectPatient, + updateStates, +} from '../Redux/actions' +import { store } from '../Redux/store' +import Loader from '../Loader' +import actionTypes from '../Redux/actionTypes' import { rowsToGraph, letterToCode } from '../../util/parse' import normalize from '../../util/normalize' import DatePicker from '../DatePicker' @@ -18,10 +27,10 @@ const NetworkMap = ({ selectPatient, height, width, - states + states, }) => { const graphRef = useRef() - const [isLoading, setIsLoading] = useState(true) + const [showLoader, setShowLoader] = useState(true) const [toolTipPosition, setToolTipPosition] = useState(null) const [tooltipContent, setToolTipContent] = useState('') const toolTipVisible = useMemo(() => { @@ -31,8 +40,39 @@ const NetworkMap = ({ searchTerm: state.searchTerm, selected: state.patient, })) + + const options = { + layout: { + hierarchical: false, + improvedLayout: true, + }, + edges: { + color: '#000000', + smooth: { + type: 'continuous', + }, + }, + nodes: { + chosen: { + node: (values, id, selected, hovering) => { + values.color = selected ? '#000' : 'green' + }, + }, + }, + height: height, + width: width, + interaction: { + navigationButtons: true, + hover: true, + }, + physics: { + enabled: true, + }, + autoResize: true, + } + useEffect(() => { - if(!states){ + if (!states) { fetch('https://api.covid19india.org/state_district_wise.json', { cors: 'no-cors', method: 'GET', @@ -40,15 +80,13 @@ const NetworkMap = ({ }) .then(resp => resp.json()) .then(res => { - if(res){ - let stateNames = Object.keys(res); - updateStates(stateNames); + if (res) { + let stateNames = Object.keys(res) + updateStates(stateNames) } }) } - }) - useEffect(() => { fetch('https://api.rootnet.in/covid19-in/unofficial/covid19india.org', { cors: 'no-cors', method: 'GET', @@ -59,10 +97,9 @@ const NetworkMap = ({ updateGraph(rowsToGraph(res.data.rawPatientData)) updatePatients(normalize(res.data.rawPatientData)) updateLastRefreshed(res.data.lastRefreshed) - setIsLoading(false) }) .catch(err => console.log('error', err)) - }, [isLoading]) + }, []) useEffect(() => { // TODO: Figure out a way to make this do-able with patient Id search @@ -73,15 +110,12 @@ const NetworkMap = ({ scale: 1.5, offset: { x: 0, y: 0 }, animation: { - duration: 500, + duration: 250, easingFunction: 'easeInCubic', }, } graphRef.current.Network.moveTo(moveParams) } - }, [selected]) - - useEffect(() => { // TODO: Add search by age, district, etc. if (graphRef.current && searchTerm) { // Make sure the ref is ready @@ -94,29 +128,25 @@ const NetworkMap = ({ // None found. TODO: Add a UI response } } - }, [searchTerm]) - const options = { - layout: { - hierarchical: false, - }, - edges: { - color: '#000000', - }, - nodes: { - chosen: { - node: (values, id, selected, hovering) => { - values.color = selected ? '#000' : 'green' - }, - }, - }, - height: height, - width: width, - interaction: { - navigationButtons: true, - hover: true, - }, - } + const unsubscribe = store.subscribe(() => { + const { type } = store.getState() + if (type === actionTypes.UPDATE_GRAPH) { + if (!showLoader) { + setShowLoader(true) + } + if (showLoader) { + const timeout = setTimeout(() => { + // setShowLoader(false) + }, 500) + return () => { + clearTimeout(timeout) + unsubscribe() + } + } + } + }) + }, [selected, searchTerm, showLoader]) const events = { select: function(event) { @@ -148,18 +178,22 @@ const NetworkMap = ({ setToolTipPosition(null) }, } - + return (
- {isLoading ? null : ( + {showLoader ? ( + + ) : ( <> - + {graph && ( + + )} {toolTipVisible && ( { let { graph, searchTerm, filter, states } = state - return { graph, searchTerm, filter, states} + return { graph, searchTerm, filter, states } } export default connect(mapStateToProps, { diff --git a/components/NetworkMapLegend/index.js b/components/NetworkMapLegend/index.js index d8fb572..56a9dd5 100644 --- a/components/NetworkMapLegend/index.js +++ b/components/NetworkMapLegend/index.js @@ -4,10 +4,10 @@ import { male_hosp, male_cured, male_dead, - state_node, - city_node, - plane_abroad_node, - plane_local_node, + state, + city, + plane_abroad, + plane_local, } from '../../images/index' @@ -79,14 +79,14 @@ const NetworkMapLegend = ({ currentFilter }) => { {['State', 'City'].includes(currentFilter) ? - + : null } {currentFilter === 'City' ? - + : null @@ -94,11 +94,11 @@ const NetworkMapLegend = ({ currentFilter }) => { {currentFilter === 'Travel' ? <> - + - + diff --git a/components/Redux/actions.js b/components/Redux/actions.js index f5658bd..9197d18 100644 --- a/components/Redux/actions.js +++ b/components/Redux/actions.js @@ -65,7 +65,6 @@ const setSearchTerm = term => (dispatch, getState) => { } const updateStates = states => (dispatch, getState) => { - console.log('Action updateStates', states); dispatch({ type: actionTypes.UPDATE_STATES, payload: { diff --git a/components/Redux/reducers.js b/components/Redux/reducers.js index f774e3b..f6b0dd9 100644 --- a/components/Redux/reducers.js +++ b/components/Redux/reducers.js @@ -20,26 +20,27 @@ const initialState = { // Export the Device Reducer. export default (state = initialState, action) => { + const type = action.type switch (action.type) { case actionTypes.SELECT_FILTER: { const { filter } = action.payload - return { ...state, filter: filter } + return { ...state, filter, type } } case actionTypes.SEARCH: { const { term } = action.payload - return { ...state, searchTerm: term } + return { ...state, searchTerm: term, type } } case actionTypes.UPDATE_GRAPH: { const { graph } = action.payload - return { ...state, graph: graph } + return { ...state, graph, type } } case actionTypes.UPDATE_PATIENTS: { const { patients } = action.payload - return { ...state, patients: patients, patient: patients.byId[251] } // `P1` in code + return { ...state, patients, patient: patients.byId[251], type } // `P1` in code } case actionTypes.UPDATE_LAST_REFRESHED: { const { lastRefreshed } = action.payload - return { ...state, lastRefreshed: lastRefreshed } + return { ...state, lastRefreshed, type } } case actionTypes.SELECT_PATIENT: { const { id, coords } = action.payload @@ -49,14 +50,14 @@ export default (state = initialState, action) => { ...patients.byId[id], coords } - return existingPatient ? { ...state, patient } : state + return existingPatient ? { ...state, patient, type } : {...state, type} } case actionTypes.UPDATE_STATES: { let states = action.payload.states.reduce((accumulator, currentValue) => { accumulator[currentValue] = hash(currentValue); return accumulator; },{}); - return {...state, states: states} + return {...state, states, type} } default: return state diff --git a/components/SidePanel/datagrid.js b/components/SidePanel/datagrid.js index f902f1b..00585cf 100644 --- a/components/SidePanel/datagrid.js +++ b/components/SidePanel/datagrid.js @@ -20,21 +20,21 @@ const A = styled.a` padding-bottom: 10px; ` -function Cell({ name, children }) { - const CellContainer = styled.div` - font-family: 'Lato', sans-serif; - background: #fff; - border-radius: 5px; - border: 1px solid #e7e7e7; - padding: 15px 20px; - ` +const CellContainer = styled.div` +font-family: 'Lato', sans-serif; +background: #fff; +border-radius: 5px; +border: 1px solid #e7e7e7; +padding: 15px 20px; +` - const Name = styled.div` - font-weight: 600; - text-transform: uppercase; - margin-bottom: 10px; - ` +const Name = styled.div` +font-weight: 600; +text-transform: uppercase; +margin-bottom: 10px; +` +function Cell({ name, children }) { return ( {name} diff --git a/images/female/cured.png b/images/female/cured.png deleted file mode 100644 index b307487..0000000 Binary files a/images/female/cured.png and /dev/null differ diff --git a/images/female/dead.png b/images/female/dead.png deleted file mode 100644 index 204af92..0000000 Binary files a/images/female/dead.png and /dev/null differ diff --git a/images/female/hospitalized.png b/images/female/hospitalized.png deleted file mode 100644 index ebdf5aa..0000000 Binary files a/images/female/hospitalized.png and /dev/null differ diff --git a/images/filter/abroad.png b/images/filter/abroad.png deleted file mode 100644 index dc6d14b..0000000 Binary files a/images/filter/abroad.png and /dev/null differ diff --git a/images/filter/city.png b/images/filter/city.png deleted file mode 100644 index 5fe0230..0000000 Binary files a/images/filter/city.png and /dev/null differ diff --git a/images/filter/p2p.png b/images/filter/p2p.png deleted file mode 100644 index c21578d..0000000 Binary files a/images/filter/p2p.png and /dev/null differ diff --git a/images/filter/state.png b/images/filter/state.png deleted file mode 100644 index 1099e8d..0000000 Binary files a/images/filter/state.png and /dev/null differ diff --git a/images/index.js b/images/index.js index f6f7315..cbb5788 100644 --- a/images/index.js +++ b/images/index.js @@ -1,19 +1,17 @@ -import male_cured from './male/cured.png' -import male_dead from './male/dead.png' -import male_hosp from './male/hospitalized.png' -import female_cured from './female/cured.png' -import female_dead from './female/dead.png' -import female_hosp from './female/hospitalized.png' +import male_cured from './svg/male/cured.svg' +import male_dead from './svg/male/dead.svg' +import male_hosp from './svg/male/hospitalized.svg' -import abroad from './filter/abroad.png' -import state from './filter/state.png' -import city from './filter/city.png' -import p2p from './filter/p2p.png' +import female_cured from './svg/female/cured.svg' +import female_dead from './svg/female/dead.svg' +import female_hosp from './svg/female/hospitalized.svg' -import state_node from './nodes/state.png' -import city_node from './nodes/city.png' -import plane_abroad_node from './nodes/plane.png' -import plane_local_node from './nodes/plane_local.png' +import p2p from './svg/p2p.svg' +import state from './svg/state.svg' +import city from './svg/city.svg' +import abroad from './svg/abroad.svg' +import plane_abroad from './svg/plane.svg' +import plane_local from './svg/plane_local.svg' export { male_cured, @@ -24,10 +22,8 @@ export { female_hosp, state, city, - state_node, p2p, - city_node, abroad, - plane_abroad_node, - plane_local_node, + plane_abroad, + plane_local, } diff --git a/images/male/cured.png b/images/male/cured.png deleted file mode 100644 index 9fe7ce5..0000000 Binary files a/images/male/cured.png and /dev/null differ diff --git a/images/male/dead.png b/images/male/dead.png deleted file mode 100644 index 2ea842a..0000000 Binary files a/images/male/dead.png and /dev/null differ diff --git a/images/male/hospitalized.png b/images/male/hospitalized.png deleted file mode 100644 index cd7e276..0000000 Binary files a/images/male/hospitalized.png and /dev/null differ diff --git a/images/nodes/city.png b/images/nodes/city.png deleted file mode 100644 index a67a98c..0000000 Binary files a/images/nodes/city.png and /dev/null differ diff --git a/images/nodes/plane.png b/images/nodes/plane.png deleted file mode 100644 index 10ebb82..0000000 Binary files a/images/nodes/plane.png and /dev/null differ diff --git a/images/nodes/plane_local.png b/images/nodes/plane_local.png deleted file mode 100644 index c4fe570..0000000 Binary files a/images/nodes/plane_local.png and /dev/null differ diff --git a/images/nodes/state.png b/images/nodes/state.png deleted file mode 100644 index e65ea5c..0000000 Binary files a/images/nodes/state.png and /dev/null differ diff --git a/images/svg/abroad.svg b/images/svg/abroad.svg new file mode 100644 index 0000000..a87d830 --- /dev/null +++ b/images/svg/abroad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/svg/city.svg b/images/svg/city.svg new file mode 100644 index 0000000..5fe1a2d --- /dev/null +++ b/images/svg/city.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/svg/female/cured.svg b/images/svg/female/cured.svg new file mode 100644 index 0000000..c812d65 --- /dev/null +++ b/images/svg/female/cured.svg @@ -0,0 +1 @@ +user security 2 \ No newline at end of file diff --git a/images/svg/female/dead.svg b/images/svg/female/dead.svg new file mode 100644 index 0000000..9e5ee64 --- /dev/null +++ b/images/svg/female/dead.svg @@ -0,0 +1 @@ +Cancel \ No newline at end of file diff --git a/images/svg/female/hospitalized.svg b/images/svg/female/hospitalized.svg new file mode 100644 index 0000000..176b8ce --- /dev/null +++ b/images/svg/female/hospitalized.svg @@ -0,0 +1 @@ +lady nurse \ No newline at end of file diff --git a/images/svg/male/cured.svg b/images/svg/male/cured.svg new file mode 100644 index 0000000..a8fe5fa --- /dev/null +++ b/images/svg/male/cured.svg @@ -0,0 +1 @@ +security check \ No newline at end of file diff --git a/images/svg/male/dead.svg b/images/svg/male/dead.svg new file mode 100644 index 0000000..256e93e --- /dev/null +++ b/images/svg/male/dead.svg @@ -0,0 +1 @@ +Cancel User \ No newline at end of file diff --git a/images/svg/male/hospitalized.svg b/images/svg/male/hospitalized.svg new file mode 100644 index 0000000..03f1b03 --- /dev/null +++ b/images/svg/male/hospitalized.svg @@ -0,0 +1 @@ +male nurse \ No newline at end of file diff --git a/images/man.png b/images/svg/man.png similarity index 100% rename from images/man.png rename to images/svg/man.png diff --git a/images/svg/man.svg b/images/svg/man.svg new file mode 100644 index 0000000..455d847 --- /dev/null +++ b/images/svg/man.svg @@ -0,0 +1,2 @@ + +User diff --git a/images/svg/p2p.svg b/images/svg/p2p.svg new file mode 100644 index 0000000..2424b82 --- /dev/null +++ b/images/svg/p2p.svg @@ -0,0 +1,2 @@ + +Companies Network diff --git a/images/svg/plane.svg b/images/svg/plane.svg new file mode 100644 index 0000000..e413696 --- /dev/null +++ b/images/svg/plane.svg @@ -0,0 +1,2 @@ + +Departures diff --git a/images/svg/plane_local.svg b/images/svg/plane_local.svg new file mode 100644 index 0000000..7042b64 --- /dev/null +++ b/images/svg/plane_local.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/svg/state.svg b/images/svg/state.svg new file mode 100644 index 0000000..a6e2341 --- /dev/null +++ b/images/svg/state.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/woman.png b/images/svg/woman.png similarity index 100% rename from images/woman.png rename to images/svg/woman.png diff --git a/images/svg/woman.svg b/images/svg/woman.svg new file mode 100644 index 0000000..e215ea0 --- /dev/null +++ b/images/svg/woman.svg @@ -0,0 +1,2 @@ + +Female User diff --git a/util/filters/city.js b/util/filters/city.js index 5299677..14741f0 100644 --- a/util/filters/city.js +++ b/util/filters/city.js @@ -1,5 +1,5 @@ import hash from 'object-hash' -import { state_node, city_node } from '../../images' +import { state, city } from '../../images' import _ from 'lodash' import dotProp from 'dot-prop-immutable' @@ -40,7 +40,7 @@ export const addCities = (graph, patients) => { label: states[key], size: 30, shape: 'image', - image: state_node, + image: state, } let index = _.findIndex(dotProp.get(graph, 'nodes'), function(o) { return o.id == node.id @@ -58,7 +58,7 @@ export const addCities = (graph, patients) => { label: stateCitiesMap[key][cityKey], size: 20, shape: 'image', - image: city_node, + image: city, } let index = _.findIndex(dotProp.get(graph, 'nodes'), function(o) { @@ -139,7 +139,7 @@ export const removeCities = (graph, patients) => { label: states[key], size: 30, shape: 'image', - image: state_node, + image: state, } let index = _.findIndex(dotProp.get(graph, 'nodes'), function(o) { return o.id == node.id @@ -157,7 +157,7 @@ export const removeCities = (graph, patients) => { label: stateCitiesMap[key][cityKey], size: 40, shape: 'image', - image: city_node, + image: city, } let index = _.findIndex(dotProp.get(graph, 'nodes'), function(o) { @@ -230,7 +230,7 @@ export const removeCities = (graph, patients) => { // label: states[key], // size: 40, // shape: 'image', -// image: state_node, +// image: state, // } // let index = _.findIndex(dotProp.get(graph, 'nodes'), function(o) { // return o.id == key diff --git a/util/filters/state.js b/util/filters/state.js index c163f90..896a849 100644 --- a/util/filters/state.js +++ b/util/filters/state.js @@ -1,5 +1,5 @@ import hash from 'object-hash' -import { state_node } from '../../images' +import { state } from '../../images' import _ from 'lodash' import dotProp from 'dot-prop-immutable' @@ -13,7 +13,7 @@ export const addStates = (graph, patients, states) => { label: stateName, size: 40, shape: 'image', - image: state_node, + image: state, } graph = dotProp.set(graph, 'nodes', list => [...list, node]) } @@ -64,7 +64,9 @@ export const removeStates = (graph, patients, states) => { return o.to == edgeTo && o.from === edgeFrom }) - graph = dotProp.delete(graph, `edges.${edgeIndex}`) + if (edgeIndex !== -1) { + graph = dotProp.delete(graph, `edges.${edgeIndex}`) + } } return graph diff --git a/util/filters/travel.js b/util/filters/travel.js index 5503574..608b518 100644 --- a/util/filters/travel.js +++ b/util/filters/travel.js @@ -2,14 +2,15 @@ import hash from 'object-hash' import _ from 'lodash' import dotProp from 'dot-prop-immutable' -import { plane_abroad_node, plane_local_node } from '../../images' +import { plane_abroad, plane_local } from '../../images' export const addTravel = (graph, patients) => { let locations = {} for (let patientId in patients) { - if (patients[patientId].place_attributes !== null) { - patients[patientId].place_attributes.forEach(loc => { + const place_attributes = patients[patientId].place_attributes + if (place_attributes && place_attributes.length) { + place_attributes.forEach(loc => { if (!locations[hash(loc.place)]) { locations[hash(loc.place)] = loc } @@ -23,18 +24,16 @@ export const addTravel = (graph, patients) => { label: locations[loc].place, size: 30, shape: 'image', - image: locations[loc].is_foreign ? plane_abroad_node : plane_local_node, + image: locations[loc].is_foreign ? plane_abroad : plane_local, } graph = dotProp.set(graph, 'nodes', list => [...list, node]) } // Add edges from patient to location for (let patientId in patients) { - if ( - patients[patientId].place_attributes !== null && - patients[patientId].place_attributes[0] - ) { - patients[patientId].place_attributes.forEach(loc => { + const place_attributes = patients[patientId].place_attributes + if (place_attributes && place_attributes[0]) { + place_attributes.forEach(loc => { let edge = { from: hash(loc.place), to: patients[patientId].patientId, @@ -60,8 +59,9 @@ export const removeTravel = (graph, patients) => { let locations = {} for (let patientId in patients) { - if (patients[patientId].place_attributes !== null) { - patients[patientId].place_attributes.forEach(loc => { + const place_attributes = patients[patientId].place_attributes + if (place_attributes && place_attributes.length) { + place_attributes.forEach(loc => { if (!locations[hash(loc.place)]) { locations[hash(loc.place)] = loc } @@ -75,7 +75,7 @@ export const removeTravel = (graph, patients) => { label: locations[loc].place, size: 30, shape: 'image', - image: locations[loc].is_foreign ? plane_abroad_node : plane_local_node, + image: locations[loc].is_foreign ? plane_abroad : plane_local, } let index = _.findIndex(dotProp.get(graph, 'nodes'), function(o) { return o.id == node.id @@ -86,11 +86,9 @@ export const removeTravel = (graph, patients) => { } for (let patientId in patients) { - if ( - patients[patientId].place_attributes !== null && - patients[patientId].place_attributes[0] - ) { - patients[patientId].place_attributes.forEach(loc => { + const place_attributes = patients[patientId].place_attributes + if (place_attributes && place_attributes[0]) { + place_attributes.forEach(loc => { let edge = { from: hash(loc.place), to: patients[patientId].patientId, @@ -107,8 +105,9 @@ export const removeTravel = (graph, patients) => { let edgeIndex = _.findIndex(graph.edges, function(o) { return o.to == edge.to && o.from === edge.from }) - - graph = dotProp.delete(graph, `edges.${edgeIndex}`) + if (edgeIndex !== -1) { + graph = dotProp.delete(graph, `edges.${edgeIndex}`) + } }) } } diff --git a/util/parse.js b/util/parse.js index bf0d258..bf17d34 100644 --- a/util/parse.js +++ b/util/parse.js @@ -1,61 +1,3 @@ -// const graph = { -// nodes: [ -// { -// id: 1, -// label: 'Node 1', -// title: 'node 1 tootip text', -// shape: 'circularImage', -// image: 'https://avatars2.githubusercontent.com/u/14039437?v=4', -// }, -// { id: 2, label: 'Node 2', title: 'node 2 tootip text' }, -// { id: 3, label: 'Node 3', title: 'node 3 tootip text' }, -// { id: 4, label: 'Node 4', title: 'node 4 tootip text' }, -// { id: 5, label: 'Node 5', title: 'node 5 tootip text' }, -// { id: 6, label: 'Node 6', title: 'node 6 tootip text' }, -// ], -// edges: [ -// { from: 1, to: 2 }, -// { from: 1, to: 3 }, -// { from: 2, to: 4 }, -// { from: 2, to: 5 }, -// ], -// } - -// OLD, don't use this schema -// const row = { -// patientId: 'P' + rawRow['Patient number'], -// dateAnnounced: rawRow['Date Announced'], -// ageEstimate: rawRow['Age Bracket'], -// gender: rawRow['Gender'], -// city: rawRow['Detected City'], -// district: rawRow['Detected District'], -// state: rawRow['Detected State'], -// status: rawRow['Current Status'], -// notes: rawRow['Notes'], -// contractedFrom: rawRow['Contracted from which Patient (Suspected)'], -// sources: [rawRow['Source_1'], rawRow['Source_2'], rawRow['Source_3']], -// } - -// New schema -// const row = { -// patientId: parseInt(rawRow['Patient number']), // Change in frontend, used to be 'P' + rawRow['Patient Number'] -// reportedOn: rawRow['Date Announced'], -// onsetEstimate: '', -// ageEstimate: rawRow['Age Bracket'], -// gender: processGender(rawRow['Gender']), // Change in frontend, used to be 'M'/'F' -// city: rawRow['Detected City'], -// state: rawRow['Detected State'], -// district: rawRow['Detected District'], -// status: rawRow['Current Status'], -// notes: rawRow['Notes'], -// contractedFrom: rawRow['Contracted from which Patient (Suspected)'], -// sources: processSources([ -// rawRow['Source_1'], -// rawRow['Source_2'], -// rawRow['Source_3'], -// ]), -// } - import { male_hosp, male_cured, @@ -134,9 +76,4 @@ export const rowsToGraph = rows => { } }) return graph -} - -// console.log(letterToCode('P699999')) -// console.log(codeToLetter(letterToCode('P6'))) - -// console.log(jsonToGraph(dumpedRows)) +} \ No newline at end of file