Skip to content

Commit

Permalink
Merge pull request #215 from devinit/feature/api-base-url-config
Browse files Browse the repository at this point in the history
Feature |Api Base URL Config
  • Loading branch information
ThatcherK authored Dec 13, 2023
2 parents 7fa0f5c + ada5a03 commit 803ce52
Show file tree
Hide file tree
Showing 15 changed files with 102 additions and 74 deletions.
2 changes: 1 addition & 1 deletion assets/core.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions src/core/DistrictMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ const renderViz = (className) => {
const root = createRoot(chartNode);
window.DIState.addListener(() => {
dichart.showLoading();
const { map, location } = window.DIState.getState;
const { map, location, baseAPIUrl } = window.DIState.getState;

if (map) {
root.render(<DistrictMap configs={map} location={location} filters={map.filters} />);
root.render(
<DistrictMap configs={map} location={location} filters={map.filters} baseAPIUrl={baseAPIUrl} />,
);
} else {
root.render(<NoDataCentered />);
}
Expand Down
10 changes: 6 additions & 4 deletions src/core/KeyFacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ const renderViz = (className) => {
const root = createRoot(chartNode);
window.DIState.addListener(() => {
dichart.showLoading();
const { keyFacts, location } = window.DIState.getState;
const { keyFacts, location, baseAPIUrl } = window.DIState.getState;

if (keyFacts?.url || keyFacts?.dataID) {
const dataFetchFunction = keyFacts?.url ? fetchData : fetchDataFromAPI;
dataFetchFunction(keyFacts?.url || keyFacts?.dataID)
if (keyFacts?.url || (keyFacts?.dataID && baseAPIUrl)) {
const dataFetchPromise = keyFacts?.url
? fetchData(keyFacts?.url)
: fetchDataFromAPI(keyFacts?.dataID, baseAPIUrl);
dataFetchPromise
.then((data) => {
if (Array.isArray(data)) {
root.render(<KeyFacts data={data} options={keyFacts} location={location} />);
Expand Down
13 changes: 8 additions & 5 deletions src/core/SelectorDropdowns.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ const renderSelectors = (className, options = { makeSticky: false }) => {
promises.push(
new Promise((resolve) => {
selectorNode.render(
<Selectors key={uuidv4()} configs={options.selectors} onChange={options.onChange || onChange} />
<Selectors key={uuidv4()} configs={options.selectors} onChange={options.onChange || onChange} />,
);
resolve(selectorNode);
})
}),
);
});

Expand All @@ -50,6 +50,7 @@ const renderSelectors = (className, options = { makeSticky: false }) => {
dichart.showLoading();
// if not explicitly provided, get selector configs from state
const { selectors } = options.selectors ? options : window.DIState.getState;
const { baseAPIUrl } = window.DIState.getState;

if (!selectors) {
window.console.log('Waiting on state update ...');
Expand All @@ -59,10 +60,12 @@ const renderSelectors = (className, options = { makeSticky: false }) => {

if (!Array.isArray(selectors)) {
window.console.log(
'Invalid value for selectors - an Array is expected. Please review the documentation!'
'Invalid value for selectors - an Array is expected. Please review the documentation!',
);
}
rootElement.render(<Selectors configs={selectors} onChange={options.onChange || onChange} />);
rootElement.render(
<Selectors configs={selectors} onChange={options.onChange || onChange} baseAPIUrl={baseAPIUrl} />,
);
});
} else {
window.console.log('State is not defined');
Expand All @@ -72,7 +75,7 @@ const renderSelectors = (className, options = { makeSticky: false }) => {
selectorNode.parentElement.classList.add('auto-height');

resolve(rootElement);
})
}),
);
});

Expand Down
10 changes: 5 additions & 5 deletions src/core/charts/Charts.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const validConfigs = (config) => {
return true;
};

const processConfig = (config) => {
const processConfig = (config, baseAPIUrl) => {
if (!validConfigs(config)) return;

window.DICharts.handler.addChart({
Expand All @@ -68,14 +68,14 @@ const processConfig = (config) => {
dichart.showLoading();
let subCounty = defaultSelectValue;
const root = createRoot(chartNode);
root.render(<DataHandler config={config} subCounty={subCounty} />);
root.render(<DataHandler config={config} subCounty={subCounty} baseAPIUrl={baseAPIUrl} />);

if (window.DIState) {
window.DIState.addListener(() => {
const { subCounty: selectedSubCounty } = window.DIState.getState;
if (selectedSubCounty && selectedSubCounty !== subCounty) {
subCounty = selectedSubCounty;
root.render(<DataHandler config={config} subCounty={subCounty} />);
root.render(<DataHandler config={config} subCounty={subCounty} baseAPIUrl={baseAPIUrl} />);
}
});
}
Expand All @@ -91,12 +91,12 @@ const initCharts = () => {
if (window.DIState) {
let configs = [];
window.DIState.addListener(() => {
const { charts: chartConfigs } = window.DIState.getState;
const { charts: chartConfigs, baseAPIUrl } = window.DIState.getState;

// ensures that the state update that renders the charts only runs once
if (chartConfigs && configs.length !== chartConfigs.length) {
configs = chartConfigs;
configs.forEach(processConfig);
configs.forEach((config) => processConfig(config, baseAPIUrl));
}
});
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/core/components/DataHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Selectors from './Selectors';
import TableChartToggler from './TableChartToggler';

const DataHandler = (props) => {
const { data, years, setFilters, updateFilter } = useData(props.config);
const { data, years, setFilters, updateFilter } = useData(props.config, props.baseAPIUrl);
const [showing, setShowing] = useState('chart'); // alternative is "table"
const [chartType, setChartType] = useState(props.config.type || 'bar');

Expand Down Expand Up @@ -68,6 +68,7 @@ const DataHandler = (props) => {
DataHandler.propTypes = {
config: PropTypes.object,
subCounty: PropTypes.string,
baseAPIUrl: PropTypes.string,
};

DataHandler.defaultProps = {
Expand Down
2 changes: 2 additions & 0 deletions src/core/components/DistrictMap/DistrictMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ const DistrictMap = (props) => {
} = useMap(
props.location,
props.configs.formatter ? { ...coreLayer, formatter: props.configs.formatter } : coreLayer,
props.baseAPIUrl,
);
useEffect(() => {
// set map options using their caption values
Expand Down Expand Up @@ -214,6 +215,7 @@ DistrictMap.propTypes = {
fullName: PropTypes.string,
coordinates: PropTypes.array,
}),
baseAPIUrl: PropTypes.string,
};

export default DistrictMap;
10 changes: 5 additions & 5 deletions src/core/components/DistrictMap/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,16 @@ const KAYUNGA_EXCLUDE_LIST = [
'Bright Future Nursery And Primary School Kangulumira',
];

export const getSchoolMarkers = (district, schoolSpecs, dataUrl, dataID) => {
export const getSchoolMarkers = (district, schoolSpecs, dataUrl, dataID, baseAPIUrl) => {
const finalGeoJSON = {
type: 'FeatureCollection',
features: [],
};
const dataVariable = dataUrl || dataID;
const dataFetchFunction = dataUrl ? fetchData : fetchDataFromAPI;
const dataVariable = dataUrl || (dataID && baseAPIUrl);
if (!schoolSpecs || !dataVariable) return finalGeoJSON;
if (dataVariable) {
dataFetchFunction(dataVariable)
if (dataUrl || (dataID && baseAPIUrl)) {
const dataFetchPromise = dataUrl ? fetchData(dataUrl) : fetchDataFromAPI(dataID, baseAPIUrl);
dataFetchPromise
.then((data) => {
const filteredData = data.filter((row) =>
district === 'Masindi'
Expand Down
9 changes: 6 additions & 3 deletions src/core/components/Selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ const Selectors = (props) => {
};
item.options = selector.defaultValue ? [selector.defaultValue] : [];
let data = selector.data || [];
if (selector.url || selector.dataID) {
const dataFetchFunction = selector.url ? fetchData : fetchDataFromAPI;
data = await dataFetchFunction(selector.url || selector.dataID);
if (selector.url || (selector.dataID && props.baseAPIUrl)) {
const dataFetchPromise = selector.url
? fetchData(selector.url)
: fetchDataFromAPI(selector.dataID, props.baseAPIUrl);
data = await dataFetchPromise;
}
item.options = item.options.concat(
data.reduce((options, curr) => {
Expand Down Expand Up @@ -83,6 +85,7 @@ Selectors.propTypes = {
onChange: PropTypes.func,
className: PropTypes.string,
children: PropTypes.node,
baseAPIUrl: PropTypes.string,
};

export default Selectors;
11 changes: 7 additions & 4 deletions src/core/components/hooks/DistrictMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const showPopup = (popup, map, event, options) => {
const popup = new Popup({ offset: 5 });
const markerPopup = new Popup({ offset: 5 });

const useMap = (location, layer, defaultOptions = {}) => {
const useMap = (location, layer, baseAPIUrl, defaultOptions = {}) => {
const [map, setMap] = useState();
const [options, setOptions] = useState(defaultOptions);
const [data, setData] = useState([]);
Expand Down Expand Up @@ -149,9 +149,11 @@ const useMap = (location, layer, defaultOptions = {}) => {

useEffect(() => {
const fetchIndicatorData = async (url, dataID) => {
const dataFetchFunction = url ? fetchData : fetchDataFromAPI;
const indicatorData = await dataFetchFunction(url || dataID);
setData(processData(indicatorData, options.indicator, options.year));
if (url || (dataID && baseAPIUrl)) {
const dataFetchPromise = url ? fetchData(url) : fetchDataFromAPI(dataID, baseAPIUrl);
const indicatorData = await dataFetchPromise;
setData(processData(indicatorData, options.indicator, options.year));
}
};
if (options.indicator && options.year) {
setLevel(schoolLevel(options.indicator.id));
Expand All @@ -161,6 +163,7 @@ const useMap = (location, layer, defaultOptions = {}) => {
schoolLevel(options.indicator.id),
options.indicator.schoolLocationUrl,
options.indicator.schoolLocationdataID,
baseAPIUrl,
),
);
fetchIndicatorData(options.indicator.url, options.indicator.dataID);
Expand Down
8 changes: 4 additions & 4 deletions src/core/components/hooks/charts.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import fetchData, { fetchDataFromAPI } from '../../../utils/data';
import { filterData, filterDataByProperty } from '../../utils';
import { getYears } from '../../utils/charts';

const useData = (config, defaultFilters = []) => {
const useData = (config, baseAPIUrl, defaultFilters = []) => {
const { url, yearRange, dataID } = config;
const { data, error } = useSWR(url || config.className || dataID, async () => {
if (config.data && Array.isArray(config.data)) {
return config.data;
}

if (url || dataID) {
const dataFetchFunction = url ? fetchData : fetchDataFromAPI;
if (url || (dataID && baseAPIUrl)) {
const dataFetchPromise = url ? fetchData(url) : fetchDataFromAPI(dataID, baseAPIUrl);

return dataFetchFunction(url || dataID).then((originalData) =>
return dataFetchPromise.then((originalData) =>
config.filters ? filterData(originalData, config.filters) : originalData,
);
}
Expand Down
65 changes: 34 additions & 31 deletions src/core/tables/Tables.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,44 +50,47 @@ const renderTable = (config) => {
className: config.className,
d3: {
onAdd: (tableNodes) => {
const dataFetchFunction = config.url ? fetchData : fetchDataFromAPI;
dataFetchFunction(config.url || config.dataID).then((data) => {
Array.prototype.forEach.call(tableNodes, (tableNode) => {
const dichart = new window.DICharts.Chart(tableNode.parentElement);
dichart.showLoading();
if (window.DIState) {
const { baseAPIUrl } = window.DIState.getState;
const dataFetchPromise = config.url ? fetchData(config.url) : fetchDataFromAPI(config.dataID, baseAPIUrl);
dataFetchPromise.then((data) => {
Array.prototype.forEach.call(tableNodes, (tableNode) => {
const dichart = new window.DICharts.Chart(tableNode.parentElement);
dichart.showLoading();

const defaultSubCounty = defaultSelectValue;
const root = createRoot(tableNode);
let selectedSubCounty = defaultSubCounty;
let selectors = [];
const defaultSubCounty = defaultSelectValue;
const root = createRoot(tableNode);
let selectedSubCounty = defaultSubCounty;
let selectors = [];

window.DIState.addListener(() => {
dichart.showLoading();
const { subCounty } = window.DIState.getState;
if (subCounty === selectedSubCounty) return;
window.DIState.addListener(() => {
dichart.showLoading();
const { subCounty } = window.DIState.getState;
if (subCounty === selectedSubCounty) return;

selectedSubCounty = subCounty || defaultSubCounty;
const filteredData =
config.filters && config.filters.subCounties
? filterDataBySubCounty(data, selectedSubCounty, config.mapping.subCounty)
: data;
const rows = parseTableData(config, filteredData, selectedSubCounty);
root.render(<DistrictTable rows={rows} />);
selectedSubCounty = subCounty || defaultSubCounty;
const filteredData =
config.filters && config.filters.subCounties
? filterDataBySubCounty(data, selectedSubCounty, config.mapping.subCounty)
: data;
const rows = parseTableData(config, filteredData, selectedSubCounty);
root.render(<DistrictTable rows={rows} />);

if (config.selectors && config.selectors.length) {
handleSelectors(
{ data: filteredData, subCounty: selectedSubCounty, config, tableRoot: root },
selectors,
).then((updatedSelectors) => {
selectors = updatedSelectors;
});
}
if (config.selectors && config.selectors.length) {
handleSelectors(
{ data: filteredData, subCounty: selectedSubCounty, config, tableRoot: root },
selectors,
).then((updatedSelectors) => {
selectors = updatedSelectors;
});
}

dichart.hideLoading();
tableNode.parentElement.classList.add('auto-height');
dichart.hideLoading();
tableNode.parentElement.classList.add('auto-height');
});
});
});
});
}
},
},
});
Expand Down
10 changes: 8 additions & 2 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -954,8 +954,9 @@ <h3 class="type-l type-l--trailer">Crop production</h3>
colours: ['#1a3e53', '#2b6587', '#357ba5', '#78b1d4', '#ecf4f9'].reverse(),
range: [25, 50, 75, 100],
url: 'https://raw.githubusercontent.com/devinit/ug-district-dashboard-viz/dev/public/assets/data/kayunga/number_of_schools.csv',
// dataID: '12763',
schoolLocationUrl: 'https://raw.githubusercontent.com/devinit/ug-district-dashboard-viz/dev/public/assets/data/kayunga/schools-locations.csv',
yearRange: [2018, 2022],
// excludeYears: [2019, 2020, 2021],
mapping: {
location: 'subcounty',
value: 'value',
Expand All @@ -971,8 +972,10 @@ <h3 class="type-l type-l--trailer">Crop production</h3>
name: 'Number of Secondary Schools',
description: 'Description Goes Here!',
colours: ['#faa2c1', '#f06595', '#d6336c', '#c2255c', '#a61e4d'],
range: [3, 6, 10],
range:[5, 10, 15, 20],
url: 'https://raw.githubusercontent.com/devinit/ug-district-dashboard-viz/dev/public/assets/data/kayunga/number_of_schools.csv',
schoolLocationUrl: 'https://raw.githubusercontent.com/devinit/ug-district-dashboard-viz/dev/public/assets/data/kayunga/schools-locations.csv',
// schoolLocationdataID: '12763',
yearRange: [2018, 2022],
mapping: {
location: 'subcounty',
Expand Down Expand Up @@ -1280,9 +1283,11 @@ <h3 class="type-l type-l--trailer">Crop production</h3>
fullName: 'Kayunga District',
coordinates: [32.86415441783307, 0.9460935176075392]
},
baseAPIUrl: 'https://api.datahub.go.ug/kayunga/',
selectors: [{
id: 'subcounty',
url: 'https://raw.githubusercontent.com/devinit/ug-district-dashboard-viz/dev/public/assets/data/kayunga/sub-counties.csv',
// dataID: '9693',
label: 'Select sub-county',
defaultValue: {
value: 'all',
Expand All @@ -1296,6 +1301,7 @@ <h3 class="type-l type-l--trailer">Crop production</h3>
target: 'education',
className: 'dicharts--number-of-schools',
url: 'https://raw.githubusercontent.com/devinit/ug-district-dashboard-viz/dev/public/assets/data/kayunga/number_of_schools.csv',
// dataID: '12763',
type: 'area',
typeOptions: [{
value: 'area',
Expand Down
1 change: 0 additions & 1 deletion src/utils/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
// eslint-disable-next-line import/prefer-default-export
export const NO_DATA = 0;
export const BASE_DATA_API_URL = 'https://api.datahub.go.ug/document/data/';
Loading

0 comments on commit 803ce52

Please sign in to comment.