Skip to content
Snippets Groups Projects
Commit 231852fe authored by Saket Agrahari's avatar Saket Agrahari
Browse files

Merge branch 'feature/COMP-143_UI' into 'develop'

COMP-143-UI changes

See merge request !24
parents 111ff8e7 eaa91ee3
Branches
Tags
1 merge request!24COMP-143-UI changes
Source diff could not be displayed: it is too large. Options to address this: view the blob.
compendium_v2/static/images/eu_logo.png

3.76 KiB | W: | H:

compendium_v2/static/images/eu_logo.png

3.75 KiB | W: | H:

compendium_v2/static/images/eu_logo.png
compendium_v2/static/images/eu_logo.png
compendium_v2/static/images/eu_logo.png
compendium_v2/static/images/eu_logo.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -13,6 +13,7 @@ import SubOrganisation from "./pages/SubOrganisation"; ...@@ -13,6 +13,7 @@ import SubOrganisation from "./pages/SubOrganisation";
import ParentOrganisation from "./pages/ParentOrganisation"; import ParentOrganisation from "./pages/ParentOrganisation";
import ECProjects from "./pages/ECProjects"; import ECProjects from "./pages/ECProjects";
import SidebarProvider from "./helpers/SidebarProvider"; import SidebarProvider from "./helpers/SidebarProvider";
import PolicyPage from "./pages/Policy";
function App(): ReactElement { function App(): ReactElement {
...@@ -35,6 +36,7 @@ function App(): ReactElement { ...@@ -35,6 +36,7 @@ function App(): ReactElement {
<Route path="/suborganisations" element={<SubOrganisation filterSelection={filterSelection} setFilterSelection={setFilterSelection} />} /> <Route path="/suborganisations" element={<SubOrganisation filterSelection={filterSelection} setFilterSelection={setFilterSelection} />} />
<Route path="/parentorganisation" element={<ParentOrganisation filterSelection={filterSelection} setFilterSelection={setFilterSelection} />} /> <Route path="/parentorganisation" element={<ParentOrganisation filterSelection={filterSelection} setFilterSelection={setFilterSelection} />} />
<Route path="/ec-projects" element={<ECProjects filterSelection={filterSelection} setFilterSelection={setFilterSelection} />} /> <Route path="/ec-projects" element={<ECProjects filterSelection={filterSelection} setFilterSelection={setFilterSelection} />} />
<Route path="/policy" element={<PolicyPage filterSelection={filterSelection} setFilterSelection={setFilterSelection} />} />
<Route path="/data" element={<CompendiumData />} /> <Route path="/data" element={<CompendiumData />} />
<Route path="*" element={<Landing />} /> <Route path="*" element={<Landing />} />
</Routes> </Routes>
... ...
......
...@@ -136,3 +136,16 @@ export interface ECProject { ...@@ -136,3 +136,16 @@ export interface ECProject {
year: number, year: number,
project: string, project: string,
} }
export interface Policy {
nren: string,
year: number,
acceptable_use: string,
connectivity: string,
data_protection: string,
environmental: string,
equal_opportunity: string,
privacy_notice: string,
strategic_plan: string
}
...@@ -49,6 +49,11 @@ const OrganizationSidebar = () => { ...@@ -49,6 +49,11 @@ const OrganizationSidebar = () => {
<span>NREN Involvement in European Commission Projects</span> <span>NREN Involvement in European Commission Projects</span>
</Link> </Link>
</Row> </Row>
<Row>
<Link to="/policy" className="link-text-underline">
<span>NREN Policies</span>
</Link>
</Row>
</Sidebar> </Sidebar>
) )
} }
... ...
......
...@@ -3,7 +3,7 @@ import { ...@@ -3,7 +3,7 @@ import {
FundingSource, FundingSource,
FundingSourceDataset, FundingSourceDataset,
ChargingStructure, ChargingStructure,
ChargingStructureDataset, Budget, BasicDataset, NrenStaff, NrenStaffDataset, Organisation, ECProject ChargingStructureDataset, Budget, BasicDataset, NrenStaff, NrenStaffDataset, Organisation, ECProject, Policy
} from "../Schema"; } from "../Schema";
const DEFAULT_CHARGING_STRUCTURE_DATA = [ const DEFAULT_CHARGING_STRUCTURE_DATA = [
...@@ -204,6 +204,25 @@ export function createECProjectsDataLookup(projectEntries: ECProject[]) { ...@@ -204,6 +204,25 @@ export function createECProjectsDataLookup(projectEntries: ECProject[]) {
} }
export function createPolicyDataLookup(policyEntries: Policy[]) {
const policyMap = new Map<string, Map<number, Policy[]>>();
policyEntries.forEach(entry => {
let nrenEntry = policyMap.get(entry.nren);
if (!nrenEntry) {
nrenEntry = new Map<number, Policy[]>();
}
let policyList = nrenEntry.get(entry.year);
if (!policyList) {
policyList = [];
}
policyList.push(entry);
nrenEntry.set(entry.year, policyList);
policyMap.set(entry.nren, nrenEntry);
});
return policyMap;
}
export const createNRENStaffDataset = (data: NrenStaff[], roles: boolean, selectedYear: number) => { export const createNRENStaffDataset = (data: NrenStaff[], roles: boolean, selectedYear: number) => {
let categories; let categories;
... ...
......
...@@ -71,6 +71,11 @@ function CompendiumData(): ReactElement { ...@@ -71,6 +71,11 @@ function CompendiumData(): ReactElement {
<span>NREN Involvement in European Commission Projects</span> <span>NREN Involvement in European Commission Projects</span>
</Link> </Link>
</Row> </Row>
<Row>
<Link to="/policy" className="link-text-underline">
<span>NREN Policies</span>
</Link>
</Row>
</div> </div>
</CollapsibleBox> </CollapsibleBox>
</div> </div>
... ...
......
import React, { useEffect, useMemo, useState } from 'react';
import { Table } from "react-bootstrap";
import Filter from "../components/graphing/Filter"
import {
Policy,
FilterSelection
} from "../Schema";
import DataPage from '../components/DataPage';
import { createPolicyDataLookup } from '../helpers/dataconversion';
async function getData(): Promise<Policy[]> {
try {
const response = await fetch('/api/policy/');
return response.json();
} catch (error) {
console.error(`Failed to load data: ${error}`);
throw error;
}
}
function getYearsAndNrens(sourceData: Policy[]) {
const years = new Set<number>();
const nrens = new Set<string>();
sourceData.forEach(datapoint => {
years.add(datapoint.year);
nrens.add(datapoint.nren);
});
return { years: years, nrens: nrens };
}
interface inputProps {
filterSelection: FilterSelection
setFilterSelection: React.Dispatch<React.SetStateAction<FilterSelection>>
}
function getJSXFromMap(data: Map<string, Map<number, Policy[]>>) {
return Array.from(data.entries()).map(([nren, nrenMap]) => {
return Array.from(nrenMap.entries()).map(([year, policies], yearIndex) => (
<tr key={nren + year} className='dotted-border'>
<td className='pt-3 nren-column text-nowrap'>{yearIndex == 0 && nren}</td>
<td className='pt-3 year-column'>{year}</td>
<td className='pt-3 blue-column'>
{policies.map(policy => (
<ul>
{!!policy.acceptable_use && (
<li key={policy.acceptable_use}>
<a href={policy.acceptable_use} target="_blank" rel="noopener noreferrer"
style={{ textDecoration: 'none' }}>
Acceptable Use Policy
</a>
</li>
)}
{!!policy.connectivity && (
<li key={policy.connectivity}>
<a href={policy.connectivity} target="_blank" rel="noopener noreferrer"
style={{ textDecoration: 'none' }}>
Connectivity Policy
</a>
</li>
)}
{!!policy.data_protection && (
<li key={policy.data_protection}>
<a href={policy.data_protection} target="_blank" rel="noopener noreferrer"
style={{ textDecoration: 'none' }}>
Data Protection Policy
</a>
</li>
)}
{!!policy.environmental && (
<li key={policy.environmental}>
<a href={policy.environmental} target="_blank" rel="noopener noreferrer"
style={{ textDecoration: 'none' }}>
Environmental Policy
</a>
</li>
)}
{!!policy.equal_opportunity && (
<li key={policy.equal_opportunity}>
<a href={policy.equal_opportunity} target="_blank" rel="noopener noreferrer"
style={{ textDecoration: 'none'}}>
Equal Opportunity Policy
</a>
</li>
)}
{!!policy.privacy_notice && (
<li key={policy.privacy_notice}>
<a href={policy.privacy_notice} target="_blank" rel="noopener noreferrer"
style={{ textDecoration: 'none' }}>
Privacy Notice Policy
</a>
</li>
)}
{!!policy.strategic_plan && (
<li key={policy.strategic_plan}>
<a href={policy.strategic_plan} target="_blank" rel="noopener noreferrer"
style={{ textDecoration: 'none' }}>
Strategic Plan Policy
</a>
</li>
)}
</ul>
))}
</td>
</tr>
))
})
}
function PolicyPage({ filterSelection, setFilterSelection }: inputProps) {
const [policytData, setProjectData] = useState<Policy[]>();
const { years, nrens } = useMemo(
() => getYearsAndNrens(policytData || []),
[policytData]
);
const selectedData = (policytData || []).filter(project =>
filterSelection.selectedYears.includes(project.year) && filterSelection.selectedNrens.includes(project.nren)
);
const policytDataByYear = createPolicyDataLookup(selectedData);
useEffect(() => {
const loadData = async () => {
const data = await getData();
setProjectData(data);
// filter fallback for when nothing is selected (only last year for all nrens)
const { years, nrens } = getYearsAndNrens(data);
setFilterSelection(previous => {
const visibleYears = previous.selectedYears.filter(year => years.has(year));
const newSelectedYears = visibleYears.length ? previous.selectedYears : [Math.max(...years)];
const visibleNrens = previous.selectedNrens.filter(nren => nrens.has(nren));
const newSelectedNrens = visibleNrens.length ? previous.selectedNrens : [...nrens];
return { selectedYears: newSelectedYears, selectedNrens: newSelectedNrens };
});
}
loadData()
}, [setFilterSelection]);
const filterNode = <Filter
filterOptions={{ availableYears: [...years], availableNrens: [...nrens] }}
filterSelection={filterSelection}
setFilterSelection={setFilterSelection}
/>
return (
<DataPage title="NREN Policies" filter={filterNode}>
<Table borderless className='compendium-table'>
<thead>
<tr>
<th className='nren-column'>NREN</th>
<th className='year-column'>Year</th>
<th className='blue-column'>Policies</th>
</tr>
</thead>
<tbody>
{getJSXFromMap(policytDataByYear)}
</tbody>
</Table>
</DataPage>
)
}
export default PolicyPage;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment