diff --git a/compendium-frontend/src/App.tsx b/compendium-frontend/src/App.tsx index b901f69e15849f81d2955f4ddbd622075bc6e10c..ac7837e512add4d1ecb311959834ca404547f2a6 100644 --- a/compendium-frontend/src/App.tsx +++ b/compendium-frontend/src/App.tsx @@ -17,8 +17,7 @@ import TrafficVolumePage from "./pages/TrafficVolumePerNren"; import ConnectedInstitutionsURLs from "./pages/ConnectedInstitutionsURLs"; import ServicesPage from "./pages/Services"; import {ConnectivityCategory, ServiceCategory} from "./Schema"; -import ConnectivityPage from "./pages/Connectivity"; -import ConnectedProportionPage from "./pages/Connectivity"; +import ConnectedUserPage from "./pages/ConnectedUser"; const router = createBrowserRouter([ { path: "/budget", element: <BudgetPage /> }, @@ -33,13 +32,13 @@ const router = createBrowserRouter([ { path: "/traffic-volume", element: <TrafficVolumePage /> }, { path: "/data", element: <CompendiumData /> }, { path: "/institutions-urls", element: <ConnectedInstitutionsURLs /> }, - { path: "/connected-proportion", element: <ConnectedProportionPage connectivity_category={ConnectivityCategory.ConnectedProportion} /> }, - { path: "/connectivity-level", element: <ConnectivityPage connectivity_category={ConnectivityCategory.ConnectivityLevel} /> }, - { path: "/connectivity-growth", element: <ConnectivityPage connectivity_category={ConnectivityCategory.ConnectivityGrowth} /> }, - { path: "/connection-carrier", element: <ConnectivityPage connectivity_category={ConnectivityCategory.ConnectionCarrier} /> }, - { path: "/connectivity-load", element: <ConnectivityPage connectivity_category={ConnectivityCategory.ConnectivityLoad} /> }, - { path: "/commercial-charging-level", element: <ConnectivityPage connectivity_category={ConnectivityCategory.CommercialChargingLevel} /> }, - { path: "/commercial-connectivity", element: <ConnectivityPage connectivity_category={ConnectivityCategory.CommercialConnectivity} /> }, + { path: "/connected-proportion", element: <ConnectedUserPage connectivity_category={ConnectivityCategory.ConnectedProportion.toString()} /> }, + { path: "/connectivity-level", element: <ConnectedUserPage connectivity_category={ConnectivityCategory.ConnectivityLevel.toString()} /> }, + { path: "/connectivity-growth", element: <ConnectedUserPage connectivity_category={ConnectivityCategory.ConnectivityGrowth.toString()} /> }, + { path: "/connection-carrier", element: <ConnectedUserPage connectivity_category={ConnectivityCategory.ConnectionCarrier.toString()} /> }, + { path: "/connectivity-load", element: <ConnectedUserPage connectivity_category={ConnectivityCategory.ConnectivityLoad.toString()} /> }, + { path: "/commercial-charging-level", element: <ConnectedUserPage connectivity_category={ConnectivityCategory.CommercialChargingLevel.toString()} /> }, + { path: "/commercial-connectivity", element: <ConnectedUserPage connectivity_category={ConnectivityCategory.CommercialConnectivity.toString()} /> }, { path: "/network-services", element: <ServicesPage category={ServiceCategory.network_services} /> }, { path: "/isp-support-services", element: <ServicesPage category={ServiceCategory.isp_support} /> }, { path: "/security-services", element: <ServicesPage category={ServiceCategory.security} /> }, diff --git a/compendium-frontend/src/Schema.tsx b/compendium-frontend/src/Schema.tsx index c487fb26001b0ef78670217196044943f52457ce..ec5d3e6731ca68ac599cdc97be5daa3804145bf3 100644 --- a/compendium-frontend/src/Schema.tsx +++ b/compendium-frontend/src/Schema.tsx @@ -136,8 +136,8 @@ export enum ConnectivityCategory { ConnectionCarrier="carrier", ConnectivityLoad="load", ConnectivityGrowth="growth", - CommercialConnectivity="charging", - CommercialChargingLevel="commercial", + CommercialConnectivity="commercial", + CommercialChargingLevel="charging", } export interface ConnectedProportion extends NrenAndYearDatapoint { diff --git a/compendium-frontend/src/components/ConnectedUsersSidebar.tsx b/compendium-frontend/src/components/ConnectedUsersSidebar.tsx index f0b5145d914a171fe7efa31e719616434f3327fa..3edeb697ac00640e9eff2b774b49699c44d9d8f9 100644 --- a/compendium-frontend/src/components/ConnectedUsersSidebar.tsx +++ b/compendium-frontend/src/components/ConnectedUsersSidebar.tsx @@ -12,6 +12,36 @@ const ConnectedUsersSidebar = () => { <span>Connected Proportion</span> </Link> </Row> + <Row> + <Link to="/connectivity-level" className="link-text-underline"> + <span>Connectivity Level</span> + </Link> + </Row> + <Row> + <Link to="/connectivity-growth" className="link-text-underline"> + <span>Connectivity Growth</span> + </Link> + </Row> + <Row> + <Link to="/connection-carrier" className="link-text-underline"> + <span>Connection Carrier</span> + </Link> + </Row> + <Row> + <Link to="/connectivity-load" className="link-text-underline"> + <span>Connectivity Load</span> + </Link> + </Row> + <Row> + <Link to="/commercial-charging-level" className="link-text-underline"> + <span>Commercial Charging Level</span> + </Link> + </Row> + <Row> + <Link to="/commercial-connectivity" className="link-text-underline"> + <span>Commercial Connectivity</span> + </Link> + </Row> <Row> <Link to="/institutions-urls" className="link-text-underline"> <span>Connected Institutions URLs</span> diff --git a/compendium-frontend/src/helpers/ConnectivityViewComponent.tsx b/compendium-frontend/src/helpers/ConnectivityViewComponent.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6751fe021f27f3778a83239c19023bc1f7622f51 --- /dev/null +++ b/compendium-frontend/src/helpers/ConnectivityViewComponent.tsx @@ -0,0 +1,129 @@ +import React from "react"; +import CollapsibleConnectivityBox from "../components/CollapsibleConnectivityBox"; +import {Table} from "react-bootstrap"; + + +function TableRow({ title, data }) { + return ( + <tr> + <th>{title}</th> + {data.map((entry, index) => ( + <td key={index}>{entry}</td> + ))} + </tr> + ); +} + +// Create a component for rendering a table section +function TableSection({ userCategoryMap, filterSelection, title, dataKey }) { + const data: any[] = []; + userCategoryMap.forEach((nrensMap: Map<string, any>) => { + nrensMap.forEach((entry: any) => { + data.push(entry[dataKey]); + }); + }); + return <TableRow title={title} data={data} />; +} + + +function TableRowForTickIcon({ title, data }) { + return ( + <tr> + <th>{title}</th> + {data.map((entry, index) => ( + <td key={index}> + {entry ? <span>✔</span> : null} + </td> + ))} + </tr> + ); +} +function TableSectionForTickIcon({ userCategoryMapForCarrier, filterSelection, title, dataKey ,category}) { + const data: any[] = []; + userCategoryMapForCarrier.forEach((nrensMap: Map<string, Map<string, any>>) => { + nrensMap.forEach((yearMap: Map<string, any>) => { + yearMap.forEach((entry: any) => { + if (dataKey==entry[category]) + data.push(entry[category]); + else + data.push(null); + }) + + }); + }); + return <TableRowForTickIcon title={title} data={data} />; +} + + +type UserCategoryMap = Map<string, Map<string, any>>; +type UserCategoryMapForCarrier = Map<string, Map<string, Map<string, any>>>; + +export function ConnectedUserData({ dataLookup, filterSelection, tableDataMap, isTickIcon=false, carrierCategoryList= [] }): React.ReactElement { + const result: JSX.Element[] = []; + let tableSections; + const dataLookupEntries: [string, UserCategoryMap| UserCategoryMapForCarrier][] = Array.from(dataLookup.entries()); + dataLookupEntries.forEach(([userCategory, userCategoryMap]) => { + let tableSections; + if (isTickIcon) { + // If isTickIcon is true, for UserCategoryMapForCarrier + const userCategoryMapForCarrier = userCategoryMap as UserCategoryMapForCarrier; + tableSections = Object.entries(tableDataMap).map(([title, dataKey]) => ( + <TableSectionForTickIcon + key={title} + userCategoryMapForCarrier={userCategoryMapForCarrier} + filterSelection={filterSelection} + title={title} + dataKey={dataKey} + category={(isTickIcon && carrierCategoryList.length==1)? carrierCategoryList[0] :userCategory} + /> + )); + } else { + // If isTickIcon is false + const userCategoryMapForUser = userCategoryMap as UserCategoryMap; + tableSections = Object.entries(tableDataMap).map(([title, dataKey]) => ( + <TableSection + key={title} + userCategoryMap={userCategoryMapForUser} + filterSelection={filterSelection} + title={title} + dataKey={dataKey} + /> + )); + } + const categoryContent = ( + <CollapsibleConnectivityBox title={userCategory} startCollapsed key={userCategory}> + <div className="table-responsive"> + <Table className="connectivity-table" bordered> + <colgroup> + <col span={1} style={{ width: "10%" }} /> + </colgroup> + <thead> + <tr> + <th></th> + {Array.from(userCategoryMap.entries()).map(([nrens, nrensMap]) => ( + <th key={nrens} colSpan={filterSelection.selectedYears.length}> + {nrens} + </th> + ))} + </tr> + <tr> + <th></th> + {Array.from(userCategoryMap.entries()).map(([nrens, nrensMap]) => ( + Array.from(nrensMap.entries()).map(([yearRef, entry]) => ( + <th key={yearRef}>{yearRef}</th> + )) + ))} + </tr> + </thead> + <tbody> + {tableSections} + </tbody> + </Table> + </div> + </CollapsibleConnectivityBox> + ); + + result.push(categoryContent); + }); + return <div className="connectivity-border">{result}</div>; +} \ No newline at end of file diff --git a/compendium-frontend/src/helpers/dataconversion.tsx b/compendium-frontend/src/helpers/dataconversion.tsx index df0d56a37d7397046bfab184dbbde555b7459b10..a844dbc0f47c97d2c03913adf470b108b3bdc186 100644 --- a/compendium-frontend/src/helpers/dataconversion.tsx +++ b/compendium-frontend/src/helpers/dataconversion.tsx @@ -318,7 +318,7 @@ export function createMatrixDataLookup<Datatype extends NrenAndYearDatapoint>(da return dataLookup; } -export function createConnectivityDataLookup<Datatype extends NrenAndYearDatapoint>(data: Datatype[], columnProperty: string){ +export function createConnectivityDataLookup<Datatype extends NrenAndYearDatapoint>(data: Datatype[], columnProperty: string,){ const dataLookup = new Map<string, Map<string, Map<number, Datatype>>>(); data.forEach(entry => { @@ -334,5 +334,59 @@ export function createConnectivityDataLookup<Datatype extends NrenAndYearDatapoi serviceEntry.set(entry.nren, nrenEntry); dataLookup.set(entry[columnProperty], serviceEntry); }); + // console.log(dataLookup) 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>>>>(); + + data.forEach(entry => { + let serviceEntry = dataLookup.get(entry[columnProperty]); + if (!serviceEntry) { + serviceEntry = new Map<string, Map<number, Map<string, Datatype>>>(); + } + let nrenEntry = serviceEntry.get(entry.nren); + if (!nrenEntry) { + nrenEntry = new Map<number, Map<string, Datatype>>(); + } + let yearEntry = nrenEntry.get(entry['carry_mechanism']); + 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); + }); + // console.log(dataLookup) + return dataLookup; +} + +export function createConnectivityDataLookupForCommercial<Datatype extends NrenAndYearDatapoint>(data: Datatype[], commercialCategory:string[]){ + const dataLookup = new Map<string, Map<string, Map<number, Map<string, Datatype>>>>(); + + commercialCategory.forEach( category =>{ + data.forEach(entry => { + let serviceEntry = dataLookup.get(category); + if (!serviceEntry) { + serviceEntry = new Map<string, Map<number, Map<string, Datatype>>>(); + } + // console.log(serviceEntry," for ",category,"-->",entry[category]) + let nrenEntry = serviceEntry.get(entry.nren); + if (!nrenEntry) { + nrenEntry = new Map<number, Map<string, Datatype>>(); + } + let yearEntry = nrenEntry.get(entry[category]); + if (!yearEntry) { + yearEntry = new Map<string, Datatype>(); + } + yearEntry.set(entry[category],entry) + nrenEntry.set(entry.year, yearEntry); + serviceEntry.set(entry.nren, nrenEntry); + dataLookup.set(category, serviceEntry); + }); + }); + // console.log(dataLookup) + return dataLookup; +} \ No newline at end of file diff --git a/compendium-frontend/src/pages/ConnectedUser.tsx b/compendium-frontend/src/pages/ConnectedUser.tsx new file mode 100644 index 0000000000000000000000000000000000000000..faf84fcc18ee66ce6cdaeb2ae792282f2662b747 --- /dev/null +++ b/compendium-frontend/src/pages/ConnectedUser.tsx @@ -0,0 +1,154 @@ +import React, { useContext } from "react"; +import {Col, Row, Table} from "react-bootstrap"; + +import {ConnectedProportion, ConnectivityCategory, Service, ServiceCategory} from "../Schema"; +import { + createConnectivityDataLookup, + createConnectivityDataLookupForCarrier, createConnectivityDataLookupForCommercial, + createMatrixDataLookup +} from "../helpers/dataconversion"; +import DataPage from "../components/DataPage"; +import Filter from "../components/graphing/Filter"; +import { ExportType, Sections } from "../helpers/constants"; +import { FilterSelectionContext } from "../helpers/FilterSelectionProvider"; +import ChartContainer from "../components/graphing/ChartContainer"; +import { useData } from "../helpers/useData"; +import {ConnectedUserData} from "../helpers/ConnectivityViewComponent"; +import CollapsibleConnectivityBox from "../components/CollapsibleConnectivityBox"; + + + +interface inputProps { + connectivity_category: string +} + +function ConnectedUserPage({ connectivity_category}: inputProps): React.ReactElement { + 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 => + 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()){ + dataLookup = createConnectivityDataLookupForCarrier(selectedData, 'user_category','carry_mechanism'); + carrierCategoryList = ['carry_mechanism'] + isTickIcon = true; + // console.log("Need to get filter data for ",dataLookup) + }else if(connectivity_category==ConnectivityCategory.CommercialConnectivity.toString()) { + 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()){ + const commercialChargingCategoryList =['collaboration','service_supplier','direct_peering'] + isTickIcon = true; + dataLookup = createConnectivityDataLookupForCommercial(selectedData, commercialChargingCategoryList); + }else { + dataLookup = createConnectivityDataLookup(selectedData, 'user_category'); + } + + const filterNode = <Filter + filterOptions={{ availableYears: [...years], availableNrens: [...nrens.values()] }} + filterSelection={filterSelection} + setFilterSelection={setFilterSelection} + /> + + const showYears = [...filterSelection.selectedYears.filter(year => years.has(year))].sort(); + + const questionMap={ + "proportion": "An estimate of portion of institute of different type which are provided with IP Connectivity by their NREN, " + + "Including information on the remit of the NREN, actual number of institution connected, market share and number of user.", + "level": "An estimate of portion of institute of different type which are provided with IP Connectivity by their NREN, " + + "Including information on the remit of the NREN, actual number of institution connected, market share and number of user.", + "carrier": "An estimate of portion of institute of different type which are provided with IP Connectivity by their NREN, " + + "Including information on the remit of the NREN, actual number of institution connected, market share and number of user.", + "load": "An estimate of portion of institute of different type which are provided with IP Connectivity by their NREN, " + + "Including information on the remit of the NREN, actual number of institution connected, market share and number of user.", + "growth": "An estimate of portion of institute of different type which are provided with IP Connectivity by their NREN, " + + "Including information on the remit of the NREN, actual number of institution connected, market share and number of user.", + "charging": "An estimate of portion of institute of different type which are provided with IP Connectivity by their NREN, " + + "Including information on the remit of the NREN, actual number of institution connected, market share and number of user.", + "commercial": "An estimate of portion of institute of different type which are provided with IP Connectivity by their NREN, " + + "Including information on the remit of the NREN, actual number of institution connected, market share and number of user.", + } + + const dataKeyMap = { + "proportion": { + "Remit cover connectivity": "coverage", + "Number of institutions connected": "number_connected", + "Percentage market share of institutions connected": "market_share", + "Number of users served": "users_served", + }, + "level": { + "Typical Speed": "typical_speed", + "Highest Speed": "highest_speed", + "Highest Speed Proportion": "highest_speed_proportion", + }, + "carrier": { + "other": "other", + "Commercial Provider Backbone":"commercial_provider_backbone", + "Nren Local Loops":"nren_local_loops", + "Regional Nren Backbone":"regional_nren_backbone", + "Man":"man", + + }, + "load": { + "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" + }, + "growth": { + "Percentage growth": "growth" + }, + "charging": { + "no_charges_if_r_e_requested": "no_charges_if_r_e_requested", + "same_as_r_e_charges":"same_as_r_e_charges", + "higher_than_r_e_charges":"higher_than_r_e_charges", + "lower_than_r_e_charges": "lower_than_r_e_charges" + }, + "commercial": { + "no_but_direct_peering":"no_but_direct_peering", + "no_policy": "no_policy", + "yes_national_nren":"yes_national_nren", + "yes_incl_other":"yes_incl_other", + "yes_if_sponsored":"yes_if_sponsored", + + } + }; + + + return ( + <DataPage title={connectivity_category} + description="Hover over the elements for additional information." + category={Sections.ConnectedUsers} filter={filterNode}> + <> + {/*<DownloadDataButton data={serviceData} filename="nren_services.csv" exportType={ExportType.CSV} />*/} + {/*<DownloadDataButton data={serviceData} filename="nren_services.xlsx" exportType={ExportType.EXCEL} />*/} + {/*<DownloadImageChartButton filename="nren_services" />*/} + <ChartContainer> + <div style={{fontSize:"16px",marginBottom:"10px",fontWeight:"bold"}}> + {questionMap[connectivity_category]} + </div> + <ConnectedUserData + dataLookup={dataLookup} + filterSelection={filterSelection} + tableDataMap={dataKeyMap[connectivity_category]} + isTickIcon={isTickIcon} + carrierCategoryList={carrierCategoryList} + /> + </ChartContainer> + </> + </DataPage> + ); +} +export default ConnectedUserPage; diff --git a/compendium-frontend/src/pages/Connectivity.tsx b/compendium-frontend/src/pages/Connectivity.tsx deleted file mode 100644 index 549b7bd825cdf55acfe184bcc89ffada855d2e2f..0000000000000000000000000000000000000000 --- a/compendium-frontend/src/pages/Connectivity.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import React, { useContext } from "react"; -import {Col, Row, Table} from "react-bootstrap"; - -import {ConnectedProportion, ConnectivityCategory, Service, ServiceCategory} from "../Schema"; -import {createConnectivityDataLookup, createMatrixDataLookup} from "../helpers/dataconversion"; -import DataPage from "../components/DataPage"; -import Filter from "../components/graphing/Filter"; -import { ExportType, Sections } from "../helpers/constants"; -import { FilterSelectionContext } from "../helpers/FilterSelectionProvider"; -import ChartContainer from "../components/graphing/ChartContainer"; -import { useData } from "../helpers/useData"; -import CollapsibleConnectivityBox from "../components/CollapsibleConnectivityBox"; - - - -interface inputProps { - connectivity_category: ConnectivityCategory -} - -function ConnectedProportionPage({ connectivity_category }: inputProps): React.ReactElement { - const { filterSelection, setFilterSelection } = useContext(FilterSelectionContext); - const { data: connectedProportion, years, nrens } = useData<ConnectedProportion>('/api/connectivity/proportion', setFilterSelection); - - const selectedData = (connectedProportion).filter(data => - filterSelection.selectedYears.includes(data.year) - && filterSelection.selectedNrens.includes(data.nren) - ); - - const connectedProportionDict = {}; - selectedData.forEach(connectedProportion => { - connectedProportionDict[connectedProportion.user_category] = connectedProportion.user_category; - }); - const connectedProportionList = Object.entries(connectedProportionDict).sort((a, b) => a[0].toLowerCase() < b[0].toLowerCase() ? -1 : 1); - - const dataLookup = createConnectivityDataLookup(selectedData, 'user_category'); - - if(connectivity_category==ConnectivityCategory.ConnectedProportion.toString()){ - console.log("Need to get filter data for ",dataLookup) - } - - const filterNode = <Filter - filterOptions={{ availableYears: [...years], availableNrens: [...nrens.values()] }} - filterSelection={filterSelection} - setFilterSelection={setFilterSelection} - /> - - const showYears = [...filterSelection.selectedYears.filter(year => years.has(year))].sort(); - - return ( - <DataPage title="Connected User" - description="Hover over the elements for additional information." - category={Sections.ConnectedUsers} filter={filterNode}> - <> - {/*<DownloadDataButton data={serviceData} filename="nren_services.csv" exportType={ExportType.CSV} />*/} - {/*<DownloadDataButton data={serviceData} filename="nren_services.xlsx" exportType={ExportType.EXCEL} />*/} - {/*<DownloadImageChartButton filename="nren_services" />*/} - <ChartContainer> - <div style={{fontSize:"16px",marginBottom:"10px",fontWeight:"bold"}}> - An estimate of portion of institiute of different type which are provided with IP Connectivity by their NREN, - Including information on the remit of the NREN, actual number of institution connected, market share and number of user. - </div> - <div className="connectivity-border"> - - {Array.from(dataLookup.entries()).map(([userCategory, userCategoryMap]) => ( - - <CollapsibleConnectivityBox title={userCategory} startCollapsed > - <div className="table-responsive"> - <Table className="connectivity-table" bordered > - <colgroup> - - <col span={1} style={{width: "10%"}}/> - </colgroup> - <thead> - <tr> - <th></th> - {Array.from(userCategoryMap.entries()).map(([nrens,nrensMap])=>( - <th key={nrens} colSpan={filterSelection.selectedYears.length}> - {nrens} - </th> - ))} - </tr> - <tr> - <th></th> - {Array.from(userCategoryMap.entries()).map(([nrens,nrensMap])=>( - Array.from(nrensMap.entries()).map(([yearRef,entry])=>( - <th key={yearRef}> - {yearRef} - </th> - )) - ))} - </tr> - </thead> - <tbody> - <tr> - <th>Remit cover connectivity</th> - {Array.from(userCategoryMap.entries()).map(([nrens,nrensMap])=>( - Array.from(nrensMap.entries()).map(([yearRef,entry])=>( - <td key={yearRef}> - {entry.coverage} - </td> - )) - ))} - </tr> - <tr> - <th>Number of institutions connected</th> - {Array.from(userCategoryMap.entries()).map(([nrens,nrensMap])=>( - Array.from(nrensMap.entries()).map(([yearRef,entry])=>( - <td key={yearRef}> - {entry.number_connected} - </td> - )) - ))} - </tr> - <tr> - <th>Percentage market share of institutions connected</th> - {Array.from(userCategoryMap.entries()).map(([nrens,nrensMap])=>( - Array.from(nrensMap.entries()).map(([yearRef,entry])=>( - <td key={yearRef}> - {entry.market_share} - </td> - )) - ))} - </tr> - <tr> - <th>Number of users served</th> - {Array.from(userCategoryMap.entries()).map(([nrens,nrensMap])=>( - Array.from(nrensMap.entries()).map(([yearRef,entry])=>( - <td key={yearRef}> - {entry.users_served} - </td> - )) - ))} - </tr> - </tbody> - </Table> - </div> - </CollapsibleConnectivityBox> - ))} - </div> - </ChartContainer> - </> - </DataPage> - ); -} -export default ConnectedProportionPage; diff --git a/compendium-frontend/src/scss/layout/_components.scss b/compendium-frontend/src/scss/layout/_components.scss index feafab829f332754da99f79531496c05fd527e95..e2a646468fff6b4ea6792ab35f7b42868285b9b8 100644 --- a/compendium-frontend/src/scss/layout/_components.scss +++ b/compendium-frontend/src/scss/layout/_components.scss @@ -73,7 +73,7 @@ border: 2px solid lightblue; padding: 10px; width: 90rem; - max-width: 68vw; + max-width: 97%; } .collapsible-content {