From c42b5940108b881317bf99a7a71fd0430456c896 Mon Sep 17 00:00:00 2001 From: manik Date: Sun, 12 Apr 2020 13:54:57 +0530 Subject: [PATCH 1/2] updated the parse.js for faster parsing of data. added a loading flag for the graph when data is being updated. --- components/DatePicker.js | 7 +-- components/NetworkMap/index.js | 13 +++-- components/Redux/actionTypes.js | 1 + components/Redux/actions.js | 9 +++- components/Redux/reducers.js | 8 ++- components/SidePanel/header.js | 12 +++-- util/parse.js | 93 ++++++++++++++------------------- 7 files changed, 74 insertions(+), 69 deletions(-) diff --git a/components/DatePicker.js b/components/DatePicker.js index 2a2dec3..a4e7e38 100644 --- a/components/DatePicker.js +++ b/components/DatePicker.js @@ -3,7 +3,7 @@ import styled from 'styled-components' import DayPicker from 'react-day-picker' import { connect } from 'react-redux' -import { updateGraph, selectFilter } from './Redux/actions' +import { updateGraph, selectFilter, updateIsLoading } from './Redux/actions' import { rowsToGraph } from '../util/parse' import { isBrowser } from 'react-device-detect' @@ -26,13 +26,14 @@ const DatePickerButton = styled.button` border: 1px solid #e7e7e7; ` -function DatePicker({ updateGraph, selectFilter }) { +function DatePicker({ updateGraph, selectFilter, updateIsLoading }) { const [selectedDay, changeSelectedDay] = useState(new Date()); const [isDayPickerVisible, changeDayPickerVisibility] = useState(false); const toggleDayPickerVisibility = () => changeDayPickerVisibility(!isDayPickerVisible); function handleDayClick(date, modifiers) { + updateIsLoading(true) // Do not proceed with click action if the date is disabled if(modifiers.disabled){ @@ -109,4 +110,4 @@ function DatePicker({ updateGraph, selectFilter }) { ) } -export default connect(null, { updateGraph, selectFilter })(DatePicker) +export default connect(null, { updateGraph, selectFilter, updateIsLoading })(DatePicker) diff --git a/components/NetworkMap/index.js b/components/NetworkMap/index.js index f6342bd..48eb1ea 100644 --- a/components/NetworkMap/index.js +++ b/components/NetworkMap/index.js @@ -2,7 +2,7 @@ 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, updateIsLoading } from '../Redux/actions' import { rowsToGraph, letterToCode } from '../../util/parse' import normalize from '../../util/normalize' import DatePicker from '../DatePicker' @@ -18,7 +18,8 @@ const NetworkMap = ({ selectPatient, height, width, - states + states, + isLoading: isGraphLoading, }) => { const graphRef = useRef() const [isLoading, setIsLoading] = useState(true) @@ -154,12 +155,14 @@ const NetworkMap = ({ {isLoading ? null : ( <> - + )} {toolTipVisible && ( { - let { graph, searchTerm, filter, states } = state - return { graph, searchTerm, filter, states} + let { graph, searchTerm, filter, states, isLoading } = state + return { graph, searchTerm, filter, states, isLoading} } export default connect(mapStateToProps, { diff --git a/components/Redux/actionTypes.js b/components/Redux/actionTypes.js index 1f42e27..0d65208 100644 --- a/components/Redux/actionTypes.js +++ b/components/Redux/actionTypes.js @@ -15,4 +15,5 @@ export default { SELECT_FILTER: 'SELECT_FILTER', SEARCH: 'SEARCH', UPDATE_STATES: 'UPDATE_STATES', + UPDATE_IS_LOADING: 'UPDATE_IS_LOADING', } diff --git a/components/Redux/actions.js b/components/Redux/actions.js index f5658bd..fe085bb 100644 --- a/components/Redux/actions.js +++ b/components/Redux/actions.js @@ -74,5 +74,12 @@ const updateStates = states => (dispatch, getState) => { }) } +const updateIsLoading = (isLoading) => (dispatch) => { + dispatch({ + type: actionTypes.UPDATE_IS_LOADING, + payload: isLoading, + }) +} + // Export the actions. -export { updateGraph, updatePatients, updateLastRefreshed, selectPatient, selectFilter, setSearchTerm, updateStates} +export { updateGraph, updatePatients, updateLastRefreshed, selectPatient, selectFilter, setSearchTerm, updateStates, updateIsLoading} diff --git a/components/Redux/reducers.js b/components/Redux/reducers.js index f774e3b..5430d54 100644 --- a/components/Redux/reducers.js +++ b/components/Redux/reducers.js @@ -15,7 +15,8 @@ const initialState = { graph: null, patients: null, searchTerm: '', - states: null + states: null, + isLoading: true, } // Export the Device Reducer. @@ -31,7 +32,7 @@ export default (state = initialState, action) => { } case actionTypes.UPDATE_GRAPH: { const { graph } = action.payload - return { ...state, graph: graph } + return { ...state, graph: graph, isLoading: false } } case actionTypes.UPDATE_PATIENTS: { const { patients } = action.payload @@ -58,6 +59,9 @@ export default (state = initialState, action) => { },{}); return {...state, states: states} } + case actionTypes.UPDATE_IS_LOADING: { + return {...state, isLoading: action.payload} + } default: return state } diff --git a/components/SidePanel/header.js b/components/SidePanel/header.js index de7099d..fff6588 100644 --- a/components/SidePanel/header.js +++ b/components/SidePanel/header.js @@ -4,7 +4,7 @@ import { connect } from 'react-redux' import {getIcon, rowsToGraph} from '../../util/parse' import { SearchInput } from '../UI/search-input' -import {selectFilter, setSearchTerm, updateGraph} from '../Redux/actions' +import {selectFilter, setSearchTerm, updateGraph, updateIsLoading} from '../Redux/actions' const Container = styled.div` font-family: 'Lato', sans-serif; @@ -45,7 +45,8 @@ const Name = styled.div` font-size: 40px; ` -function Header({ patient, lastRefreshed, setSearchTerm, selectFilter, updateGraph }) { +function Header({ patient, lastRefreshed, setSearchTerm, selectFilter, updateGraph, updateIsLoading }) { + const [isMounting, toggleIsMounting] = useState(true) const [removeLeafNode, toggleRemoveLeafNode] = useState(false) const onSearch = (term) => { let _serchTerm = term.toUpperCase().replace(/P/g, "").trim(); @@ -65,6 +66,11 @@ function Header({ patient, lastRefreshed, setSearchTerm, selectFilter, updateGra } useEffect(() => { + if (isMounting) { + toggleIsMounting(false) + return + } + updateIsLoading(true) fetch('https://api.rootnet.in/covid19-in/unofficial/covid19india.org', { cors: 'no-cors', method: 'GET', @@ -99,5 +105,5 @@ function Header({ patient, lastRefreshed, setSearchTerm, selectFilter, updateGra } export default connect(null, { - setSearchTerm, updateGraph, selectFilter + setSearchTerm, updateGraph, selectFilter, updateIsLoading, })(Header) diff --git a/util/parse.js b/util/parse.js index 7b540be..467ca08 100644 --- a/util/parse.js +++ b/util/parse.js @@ -66,7 +66,6 @@ import { cluster_node, } from '../images/index' import hash from 'object-hash' -import dotProp from 'dot-prop-immutable' export function letterToCode(str) { const letterPos = parseInt(str[0], 36) @@ -74,28 +73,16 @@ export function letterToCode(str) { } export function getIcon(patient) { - if (patient.gender === 'male') { - if (patient.status === 'Recovered') { - return male_cured - } else if (patient.status === 'Hospitalized') { - return male_hosp - } else if (patient.status === 'Deceased') { - return male_dead - } else { - return male_hosp - } - } else if (patient.gender === 'female') { - if (patient.status === 'Recovered') { - return female_cured - } else if (patient.status === 'Hospitalized') { - return female_hosp - } else if (patient.status === 'Deceased') { - return female_dead - } else { - return female_hosp - } - } else { - return female_hosp + console.log('entered getIcon') + switch (patient.status) { + case 'Recovered': + return patient.gender === 'male' ? male_cured : female_cured + case 'Hospitalized': + return patient.gender === 'male' ? male_hosp : female_hosp + case 'Deceased': + return patient.gender === 'male' ? male_dead : female_dead + default: + return patient.gender === 'male' ? male_hosp : female_hosp } } @@ -110,7 +97,7 @@ export const codeToLetter = code => { const extractEvents = rows => {} -function addPatientNode(patientCode, row, graph) { +function getPatientNode(patientCode, row) { let node = { id: patientCode, label: 'P' + row.patientId, @@ -119,27 +106,7 @@ function addPatientNode(patientCode, row, graph) { group: 'patient' } - graph = dotProp.set(graph, 'nodes', list => [...list, node]) - return graph; -} - -function addClusterNode(row, clusters, graph) { - if (row.contractedFrom) { - if (!clusters[hash(row.contractedFrom)] && row.contractedFrom[0] === 'E') { - const patientCode = letterToCode(row.contractedFrom) - clusters[hash(row.contractedFrom)] = row.contractedFrom - - let clusterNode = { - id: patientCode, - label: 'Event ' + row.contractedFrom[1], - shape: 'image', - size: 60, - image: cluster_node, - } - graph = dotProp.set(graph, 'nodes', list => [...list, clusterNode]) - } - } - return graph; + return node } export const rowsToGraph = (rows, removeLeafNode) => { @@ -163,26 +130,42 @@ export const rowsToGraph = (rows, removeLeafNode) => { rows.forEach(row => { const patientCode = letterToCode('P' + row.patientId) if (row.contractedFrom) { + const CONTRACTED_FROM = row.contractedFrom + const PATIENT_CODE_CONTRACTED_FROM = letterToCode(CONTRACTED_FROM) let edge = {} - if (row.contractedFrom[0] === 'E') { + if (CONTRACTED_FROM[0] === 'E') { edge = { - from: letterToCode(row.contractedFrom), + from: PATIENT_CODE_CONTRACTED_FROM, to: patientCode, length: 500, dashes: true, - }} else { + } + const CONTRACTED_FROM_HASH = hash(CONTRACTED_FROM) + // adding the cluster node + if (!clusters[CONTRACTED_FROM_HASH]) { + clusters[CONTRACTED_FROM_HASH] = CONTRACTED_FROM + + let clusterNode = { + id: PATIENT_CODE_CONTRACTED_FROM, + label: 'Event ' + CONTRACTED_FROM[1], + shape: 'image', + size: 60, + image: cluster_node, + } + graph.nodes.push(clusterNode) + } + } else { edge = { - from: letterToCode(row.contractedFrom), + from: PATIENT_CODE_CONTRACTED_FROM, to: patientCode, } } - graph = dotProp.set(graph, 'edges', list => [...list, edge]) + graph.edges.push(edge) } - graph = addClusterNode(row, clusters, graph); - if(removeLeafNode && listOfConnectedCases.has(patientCode) ) { - graph = addPatientNode(patientCode, row, graph); - }else if(!removeLeafNode){ - graph = addPatientNode(patientCode, row, graph); + if (!removeLeafNode) { + graph.nodes.push(getPatientNode(patientCode, row)) + } else if (listOfConnectedCases.has(patientCode)) { + graph.nodes.push(getPatientNode(patientCode, row)) } }) return graph From c9bea102720a795a6993c65e5568608aaa10110b Mon Sep 17 00:00:00 2001 From: manik Date: Sun, 12 Apr 2020 14:00:10 +0530 Subject: [PATCH 2/2] removed the console log --- util/parse.js | 1 - 1 file changed, 1 deletion(-) diff --git a/util/parse.js b/util/parse.js index 467ca08..6732deb 100644 --- a/util/parse.js +++ b/util/parse.js @@ -73,7 +73,6 @@ export function letterToCode(str) { } export function getIcon(patient) { - console.log('entered getIcon') switch (patient.status) { case 'Recovered': return patient.gender === 'male' ? male_cured : female_cured