Skip to content
Snippets Groups Projects
Commit 0f5c0d85 authored by Bjarke Madsen's avatar Bjarke Madsen
Browse files

WIP ConnectedUser refactor

parent 289470cf
No related branches found
No related tags found
1 merge request!134Refactor
......@@ -4,7 +4,6 @@ import {
Budget, BasicDataset, NrenStaff, TrafficVolume, NrenAndYearDatapoint,
TrafficRatio
} from "../Schema";
import { remitCover } from "./ConnectivityDisplayConstant";
// create a color from a string, credits https://stackoverflow.com/a/16348977
const stringToColour = function (str) {
......@@ -279,9 +278,9 @@ export const createNRENStaffDataset = (data: NrenStaff[], roles: boolean, select
export const createTrafficRatioDataset = (data: TrafficRatio[], selectedYear: number) => {
const categories = [
"Research & Education",
"Commodity"
]
"Research & Education",
"Commodity"
]
const fields = {
"Research & Education": "r_and_e_percentage",
"Commodity": "commodity_percentage"
......@@ -496,7 +495,7 @@ export function createMatrixDataLookupForArrayColumnType<Datatype extends NrenAn
const dataLookup = new Map<string, Map<string, Map<number, Datatype>>>();
data.forEach(entry => {
let nrenEntry = dataLookup.get(entry.nren) ?? new Map<string, Map<number, Datatype>>();
const nrenEntry = dataLookup.get(entry.nren) ?? new Map<string, Map<number, Datatype>>();
// Iterate over the array and set each element as a key in the map
const columnPropertyArray = entry[columnPropertyName];
......@@ -515,25 +514,6 @@ export function createMatrixDataLookupForArrayColumnType<Datatype extends NrenAn
}
export function createConnectivityDataLookup<Datatype extends NrenAndYearDatapoint>(data: Datatype[], columnProperty: string,) {
const dataLookup = new Map<string, Map<string, Map<number, Datatype>>>();
data.forEach(entry => {
let serviceEntry = dataLookup.get(entry[columnProperty]);
if (!serviceEntry) {
serviceEntry = new Map<string, Map<number, Datatype>>();
}
let nrenEntry = serviceEntry.get(entry.nren);
if (!nrenEntry) {
nrenEntry = new Map<number, Datatype>();
}
nrenEntry.set(entry.year, entry);
serviceEntry.set(entry.nren, nrenEntry);
dataLookup.set(entry[columnProperty], serviceEntry);
});
return dataLookup;
}
export function createConnectivityDataLookupForCarrier<Datatype extends NrenAndYearDatapoint>(data: Datatype[], columnProperty: string, enumCategory) {
const dataLookup = new Map<string, Map<string, Map<number, Map<string, Datatype>>>>();
......@@ -558,26 +538,26 @@ export function createConnectivityDataLookupForCarrier<Datatype extends NrenAndY
return dataLookup;
}
export function createConnectivityDataLookupForServicesOffered<Datatype extends NrenAndYearDatapoint>(data: Datatype[], columnProperty: string, enumCategory) {
export function createConnectivityDataLookupForServicesOffered<Datatype extends NrenAndYearDatapoint>(data: Datatype[], columnProperty: string) {
const dataLookup = new Map<string, Map<string, Map<number, Map<string, Datatype>>>>();
data.forEach(entry => {
let serviceEntry = dataLookup.get(entry[columnProperty]);
data.forEach(dataPoint => {
let serviceEntry = dataLookup.get(dataPoint[columnProperty]);
if (!serviceEntry) {
serviceEntry = new Map<string, Map<number, Map<string, Datatype>>>();
}
let nrenEntry = serviceEntry.get(entry.nren);
let nrenEntry = serviceEntry.get(dataPoint.nren);
if (!nrenEntry) {
nrenEntry = new Map<number, Map<string, Datatype>>();
}
let yearEntry = nrenEntry.get(entry.year);
let yearEntry = nrenEntry.get(dataPoint.year);
if (!yearEntry) {
yearEntry = new Map<string, Datatype>();
}
yearEntry.set(entry[enumCategory], entry)
nrenEntry.set(entry.year, yearEntry);
serviceEntry.set(entry.nren, nrenEntry);
dataLookup.set(entry[columnProperty], serviceEntry);
yearEntry.set(dataPoint['service_category'], dataPoint)
nrenEntry.set(dataPoint.year, yearEntry);
serviceEntry.set(dataPoint.nren, nrenEntry);
dataLookup.set(dataPoint[columnProperty], serviceEntry);
});
return dataLookup;
}
......@@ -609,9 +589,46 @@ export function createConnectivityDataLookupForCommercial<Datatype extends NrenA
return dataLookup;
}
export function createConnectivityDataLookup<Datatype extends NrenAndYearDatapoint>(data: Datatype[]) {
/*
Creates a map from a number of categories (determined by the categoryField) to NREN -> Year -> Data for that year
This is used to create the matrix of data for the connected user ScrollableMatrix pages
*/
const categoryField = 'user_category';
const dataLookup = new Map<string, Map<string, Map<number, Datatype>>>();
data.forEach(entry => {
let serviceEntry = dataLookup.get(entry[categoryField]);
if (!serviceEntry) {
serviceEntry = new Map<string, Map<number, Datatype>>();
}
let nrenEntry = serviceEntry.get(entry.nren);
if (!nrenEntry) {
nrenEntry = new Map<number, Datatype>();
}
nrenEntry.set(entry.year, entry);
serviceEntry.set(entry.nren, nrenEntry);
dataLookup.set(entry[categoryField], serviceEntry);
});
return dataLookup;
}
export function createConnectivityDataLookupForConnectedProportion<Datatype extends NrenAndYearDatapoint>(data: Datatype[], columnProperty: string,) {
const dataLookup = new Map<string, Map<string, Map<number, Datatype>>>();
const valueMap = {
"yes_incl_other": "Yes - including transit to other networks",
"yes_national_nren": "Yes - national NREN access",
"sometimes": "In some circumstances",
"no_policy": "No - not eligible for policy reasons",
"no_financial": "No - financial restrictions",
"no_other": "No - other reason",
"unsure": "Unsure/unclear"
}
data.forEach(entry => {
let serviceEntry = dataLookup.get(entry[columnProperty]);
if (!serviceEntry) {
......@@ -621,7 +638,7 @@ export function createConnectivityDataLookupForConnectedProportion<Datatype exte
if (!nrenEntry) {
nrenEntry = new Map<number, Datatype>();
}
const newValue = remitCover[entry["coverage"]]
const newValue = valueMap[entry["coverage"]]
if (newValue) {
entry["coverage"] = newValue;
}
......
import React, { useContext } from "react";
import { Link } from 'react-router-dom';
import { ConnectedProportion, ConnectivityCategory } from "../../Schema";
import {
ConnectedProportion,
ConnectionCarrier,
ConnectivityGrowth,
ConnectivityLevel,
ConnectivityLoad,
ConnectivityPage
} from "../../Schema";
import {
createConnectivityDataLookup,
createConnectivityDataLookupForCarrier,
......@@ -13,49 +21,131 @@ import { Sections } from "../../helpers/constants";
import { FilterSelectionContext } from "../../providers/FilterSelectionProvider";
import ChartContainer from "../../components/graphing/ChartContainer";
import { useData } from "../../helpers/useData";
import { ConnectedUserData } from "../../helpers/ConnectivityViewComponent";
import { questionMap, dataKeyMap, displayTitle } from "../../helpers/ConnectivityDisplayConstant";
import { ScrollableMatrix } from "../../components/ScrollableMatrix";
import { UserCategories, CommercialOrgCategories, CommercialConnectionCategories } from "../../helpers/constants";
const displayTitle = {
[ConnectivityPage.ConnectedProportion]: "Proportion of Different Categories of Institutions Served by NRENs",
[ConnectivityPage.ConnectivityLevel]: "Level of IP Connectivity by Institution Type",
[ConnectivityPage.ConnectionCarrier]: "Methods of Carrying IP Traffic to Users",
[ConnectivityPage.ConnectivityLoad]: "Connectivity Load",
[ConnectivityPage.ConnectivityGrowth]: "Connectivity Growth",
[ConnectivityPage.CommercialChargingLevel]: "Commercial Charging Level",
[ConnectivityPage.CommercialConnectivity]: "Commercial Connectivity"
}
const description = {
[ConnectivityPage.ConnectedProportion]: <span>
European NRENs all have different connectivity remits, as is shown in the table below. The categories of institutions make use of the ISCED 2011 classification system, the UNESCO scheme for International Standard Classification of Education.
<br />The table shows whether a particular category of institution falls within the connectivity remit of the NREN, the actual number of such institutions connected, the % market share this represents, and the actual number of end users served in the category.
</span>,
[ConnectivityPage.ConnectivityLevel]: <span>
The table below shows the average level of connectivity for each category of institution. The connectivity remit of different NRENs is shown on a different page, and NRENs are asked, at a minimum, to provide information about the typical and highest capacities (in Mbit/s) at which Universities and Research Institutes are connected.
<br />NRENs are also asked to show proportionally how many institutions are connected at the highest capacity they offer.
</span>,
[ConnectivityPage.ConnectionCarrier]: <span>
The table below shows the different mechanisms employed by NRENs to carry traffic to the different types of users they serve.
Not all NRENs connect all of the types of institution listed below - details of connectivity remits can be found here: <Link to="/connected-proportion" className="">
<span>{displayTitle[ConnectivityPage.ConnectedProportion]}</span>
</Link>
</span>,
[ConnectivityPage.ConnectivityLoad]: <span>What are the traffic loads in Mbit/s?</span>,
[ConnectivityPage.ConnectivityGrowth]: <span>What do you expect the traffic growth to be in the next 3 years?</span>,
[ConnectivityPage.CommercialChargingLevel]: <span>What are the typical charging levels for the following types of commercial connections?</span>,
[ConnectivityPage.CommercialConnectivity]: <span>What types of commercial organisations do you connect?</span>,
}
const rowFieldMap = {
[ConnectivityPage.ConnectedProportion]: {
"Remit cover connectivity": "coverage",
"Number of institutions connected": "number_connected",
"Percentage market share of institutions connected": "market_share",
"Number of users served": "users_served",
},
[ConnectivityPage.ConnectivityLevel]: {
"Typical link speed (Mbit/s):": "typical_speed",
"Highest speed link (Mbit/s):": "highest_speed",
"Proportionally how many institutions in this category are connected at the highest capacity? (%):"
: "highest_speed_proportion",
},
[ConnectivityPage.ConnectionCarrier]: {
"Commercial Provider Backbone": "commercial_provider_backbone",
"NREN Local Loops": "nren_local_loops",
"Regional NREN Backbone": "regional_nren_backbone",
"MAN": "man",
"Other": "other",
},
[ConnectivityPage.ConnectivityLoad]: {
"Average Load From Institutions": "average_load_from_institutions",
"Average Load To Institutions": "average_load_to_institutions",
"Peak Load To Institution": "peak_load_to_institutions",
"Peak Load From Institution": "peak_load_from_institutions"
},
[ConnectivityPage.ConnectivityGrowth]: {
"Percentage growth": "growth"
},
[ConnectivityPage.CommercialChargingLevel]: {
"No charges applied if requested by R&E users": "no_charges_if_r_e_requested",
"Same charging model as for R&E users": "same_as_r_e_charges",
"Charges typically higher than for R&E users": "higher_than_r_e_charges",
"Charges typically lower than for R&E users": "lower_than_r_e_charges"
},
[ConnectivityPage.CommercialConnectivity]: {
"No - but we offer a direct or IX peering": "no_but_direct_peering",
"No - not eligible for policy reasons": "no_policy",
"No - financial restrictions (NREN is unable to charge/recover costs)": "no_financial",
"No - other reason / unsure": "no_other",
"Yes - National NREN access only": "yes_national_nren",
"Yes - Including transit to other networks": "yes_incl_other",
"Yes - only if sponsored by a connected institution": "yes_if_sponsored",
}
};
interface inputProps {
connectivity_category: string
page: ConnectivityPage
}
function ConnectedUserPage({ connectivity_category }: inputProps): React.ReactElement {
type DataFormat = ConnectedProportion | ConnectivityLevel | ConnectionCarrier | ConnectivityLoad | ConnectivityGrowth
function ConnectedUserPage({ page }: inputProps): React.ReactElement {
const apiUrl = `/api/connectivity/${page.toString()}`;
const { filterSelection, setFilterSelection } = useContext(FilterSelectionContext);
const apiUrl = '/api/connectivity/' + connectivity_category;
const { data: connectedProportion, years, nrens } = useData<ConnectedProportion>(apiUrl, setFilterSelection);
let isTickIcon = false
const selectedData = (connectedProportion).filter(data =>
const { data, years, nrens } = useData<DataFormat>(apiUrl, setFilterSelection);
const selectedData = data.filter(data =>
filterSelection.selectedYears.includes(data.year)
&& filterSelection.selectedNrens.includes(data.nren)
);
const connectedProportionDict = {};
selectedData.forEach(connectedProportion => {
connectedProportionDict[connectedProportion.user_category] = connectedProportion.user_category;
});
let dataLookup: any;
let carrierCategoryList: any;
if (connectivity_category == ConnectivityCategory.ConnectionCarrier.toString()) {
let isTickIcon = false
let dataLookup: Map<string, Map<string, Map<number, DataFormat | Map<string, DataFormat>>>>;
let categoryLookup;
if (page == ConnectivityPage.ConnectionCarrier) {
categoryLookup = UserCategories;
dataLookup = createConnectivityDataLookupForCarrier(selectedData, 'user_category', 'carry_mechanism');
carrierCategoryList = ['carry_mechanism']
isTickIcon = true;
} else if (connectivity_category == ConnectivityCategory.CommercialConnectivity.toString()) {
} else if (page == ConnectivityPage.CommercialConnectivity) {
categoryLookup = CommercialOrgCategories;
const commercialConnectivityCategoryList = ['commercial_r_and_e', 'commercial_general', 'commercial_collaboration'
, 'commercial_service_provider', 'university_spin_off']
isTickIcon = true;
dataLookup = createConnectivityDataLookupForCommercial(selectedData, commercialConnectivityCategoryList);
} else if (connectivity_category == ConnectivityCategory.CommercialChargingLevel.toString()) {
} else if (page == ConnectivityPage.CommercialChargingLevel) {
categoryLookup = CommercialConnectionCategories;
const commercialChargingCategoryList = ['collaboration', 'service_supplier', 'direct_peering']
isTickIcon = true;
dataLookup = createConnectivityDataLookupForCommercial(selectedData, commercialChargingCategoryList);
} else if (connectivity_category == ConnectivityCategory.ConnectedProportion.toString()) {
} else if (page == ConnectivityPage.ConnectedProportion) {
categoryLookup = UserCategories;
dataLookup = createConnectivityDataLookupForConnectedProportion(selectedData, 'user_category');
}
else {
dataLookup = createConnectivityDataLookup(selectedData, 'user_category');
} else {
categoryLookup = UserCategories;
dataLookup = createConnectivityDataLookup(selectedData);
}
const filterNode = <Filter
......@@ -64,24 +154,22 @@ function ConnectedUserPage({ connectivity_category }: inputProps): React.ReactEl
setFilterSelection={setFilterSelection}
/>
// contains title for each row, and the field in the data object to look up for that row
const rowInfo = rowFieldMap[page];
return (
<DataPage title={displayTitle[connectivity_category]}
description={questionMap[connectivity_category]}
<DataPage title={displayTitle[page]}
description={description[page]}
category={Sections.ConnectedUsers} filter={filterNode}
data={selectedData} filename="nren_connectivity">
<>
<div style={{ fontSize: "16px", marginBottom: "10px", fontWeight: "bold" }}>
</div>
<ChartContainer>
<ConnectedUserData
dataLookup={dataLookup}
filterSelection={filterSelection}
tableDataMap={dataKeyMap[connectivity_category]}
isTickIcon={isTickIcon}
carrierCategoryList={carrierCategoryList}
/>
</ChartContainer>
</>
<ChartContainer>
<ScrollableMatrix
dataLookup={dataLookup}
rowInfo={rowInfo}
isTickIcon={isTickIcon}
categoryLookup={categoryLookup}
/>
</ChartContainer>
</DataPage>
);
}
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment