Skip to content
Snippets Groups Projects
Select Git revision
  • 572cde477aa511f7ae25af99b535e898e96b29d5
  • develop default
  • master protected
  • feature/frontend-tests
  • 0.110
  • 0.109
  • 0.108
  • 0.107
  • 0.106
  • 0.105
  • 0.104
  • 0.103
  • 0.102
  • 0.101
  • 0.100
  • 0.99
  • 0.98
  • 0.97
  • 0.96
  • 0.95
  • 0.94
  • 0.93
  • 0.92
  • 0.91
24 results

DataAnalysis.tsx

Blame
  • DataAnalysis.tsx 10.04 KiB
    import React, { ReactElement, useEffect, useState } from 'react';
    import { Accordion, Col, Container, ListGroup, Row } from "react-bootstrap";
    import BarGraph from "../components/graphing/BarGraph";
    import LineGraph from "../components/graphing/LineGraph";
    
    import { BudgetMatrix, DataEntrySection, Budget } from "../Schema";
    // import {evaluateInteractionItems} from "chart.js/dist/core/core.interaction";
    import barGraph from "../components/graphing/BarGraph";
    
    
    export const options = {
        // indexAxis: 'y' as const,
        responsive: true,
        plugins: {
            legend: {
                position: 'top' as const,
            },
            title: {
                display: true,
                text: 'Loading...',
            },
        },
    };
    function DataAnalysis(): ReactElement {
    
        function api<T>(url: string, options: RequestInit): Promise<T> {
            return fetch(url, options)
                .then((response) => {
                    if (!response.ok) {
                        return response.text().then((message) => {
                            console.error(`Failed to load datax: ${message}`, response.status);
                            throw new Error("The data could not be loaded, check the logs for details.");
                        });
                    }
    
                    return response.json() as Promise<T>;
                })
        }
        const [budgetMatrixResponse, setBudgetMatrixResponse] = useState<BudgetMatrix>();
        const [budgetResponse, setBudget] = useState<Budget[]>();
        const [dataEntrySection, setDataEntrySection] = useState<DataEntrySection>();
        const [selectedDataEntry, setSelectedDataEntry] = useState<number>(0);
    
        useEffect(() => {
            // let timeoutRef = 0;
            const getDataEntries = () => {
                const dataEntrySectionResponse: DataEntrySection = {
                    description: "Org",
                    items: [
                        {
                            id: 2,
                            title: "NREN Budgets per year, in Millions EUR",
                            url: "/api/data-entries/item/2"
                        }
                        // {
                        //     id:3,
                        //     title:"NREN Budgets per NREN, in Millions EUR",
                        //     url:"/api/data-entries/item/3"
                        // }
                    ],
                    name: "Organisation"
                }
                setDataEntrySection(dataEntrySectionResponse);
                console.log("getDataEntries " + dataEntrySection);
                // Autoload the first graph
                if (dataEntrySectionResponse.items.length > 0) {
                    setSelectedDataEntry(dataEntrySectionResponse.items[0].id);
                }
            }
            const loadData = () => {
                console.log("selectedDataEntry " + selectedDataEntry)
                if (selectedDataEntry == 0) {
                    getDataEntries();
                    return;
                }
                console.log("budgetResponse " + budgetResponse)
                if (budgetResponse == undefined) {
                    api<Budget[]>('/api/budget', {
                        referrerPolicy: "unsafe-url",
                        headers: {
                            "Access-Control-Allow-Origin": "*",
                            "Content-Type": "text/plain",
                            "Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
                            "Access-Control-Allow-Headers": "Origin, Content-Type, X-Auth-Token"
    
                        }
                    })
                        .then((budget: Budget[]) => {
                            if (selectedDataEntry == 2)
                                options.plugins.title.text = 'NREN Budgets per year, in Millions EUR';
                            setBudget(budget)
                            console.log("API positive response Budget :  " + budget)
                            convertToBudgetPerYearDataResponse(budget)
                        })
                        .catch(error => {
                            console.log(`Error fetching from API: ${error}`);
                        })
                } else {
                    convertToBudgetPerYearDataResponse(budgetResponse)
                }
    
            }
            loadData()
        }, [selectedDataEntry]);
    
        const empty_bar_response = {
            data: {
                datasets: [
                    {
                        backgroundColor: '',
                        data: [],
                        label: ''
                    }],
                labels: []
            },
            description: "",
            id: "",
            settings: {},
            title: ""
        }
    
        const empty_budget_response = [{
            BUDGET: "",
            BUDGET_YEAR: 0,
            NREN: "",
            id: 0
        }]
    
    
        const convertToBudgetPerYearDataResponse = (budgetResponse: Budget[]) => {
            console.log("convertToBudgetPerYearDataResponse budgetResponse  " + budgetResponse);
            const barResponse = budgetResponse != undefined ? budgetResponse : empty_budget_response;
            const labelsYear = [...new Set(barResponse.map((item) => item.BUDGET_YEAR))];
            const labelsNREN = [...new Set(barResponse.map((item) => item.NREN))];
    
            console.log("convertToBudgetPerYearDataResponse  " + barResponse);
    
    
            function getRandomColor() {
                const red = Math.floor(Math.random() * 256).toString(16).padStart(2, '0'); // generates a value between 00 and ff
                const green = Math.floor(Math.random() * 256).toString(16).padStart(2, '0');
                const blue = Math.floor(Math.random() * 256).toString(16).padStart(2, '0');
                return `#${red}${green}${blue}`;
            }
    
    
            function dataForNRENForYear(year: number, nren: string) {
                const budget = barResponse.find(function (entry, index) {
                    if (entry.BUDGET_YEAR == year && entry.NREN == nren) {
                        return Number(entry.BUDGET);
                    }
                })
                return budget !== undefined ? Number(budget.BUDGET) : null;
            }
    
            const datasetPerYear = labelsYear.map(function (year) {
                const randomColor = getRandomColor();
                return {
                    backgroundColor: randomColor,
                    borderColor: randomColor,
                    data: labelsNREN.map(nren => dataForNRENForYear(year, nren)),
                    label: year.toString()
                }
            })
    
            const datasetPerNREN = labelsNREN.map(function (nren) {
                const randomColor = getRandomColor();
                return {
                    backgroundColor: randomColor,
                    borderColor: randomColor,
                    data: labelsYear.map(year => dataForNRENForYear(year, nren)),
                    label: nren
                }
            })
    
            if (selectedDataEntry == 2) {
                const dataResponse: BudgetMatrix = {
                    data: {
                        datasets: datasetPerNREN,
                        labels: labelsYear.map(l => l.toString())
                    },
                    description: "The numbers are based on 30 NRENs that " +
                        "reported their budgets continuously throughout this" +
                        " period. This means that some larger NRENs are not" +
                        " included and therefore the actual total budgets will" +
                        " have been higher. (For comparison, the total budget" +
                        " according to the 2021 survey results based on the data" +
                        " for all responding NRENs that year is €555 M). The" +
                        " percentage change is based on the previous year’s" +
                        " budget.",
                    id: "3",
                    settings: {},
                    title: 'NREN Budgets per NREN, in Millions EUR'
                }
                setBudgetMatrixResponse(dataResponse);
            }
            else {
                const dataResponse: BudgetMatrix = {
                    data: {
                        datasets: datasetPerYear,
                        labels: labelsNREN.map(l => l.toString())
                    },
                    description:
                        "The numbers are based on 30 NRENs that reported their " +
                        "budgets continuously throughout this period. This " +
                        "means that some larger NRENs are not included and " +
                        "therefore the actual total budgets will have been " +
                        "higher. (For comparison, the total budget according to" +
                        " the 2021 survey results based on the data for all" +
                        " responding NRENs that year is €555 M). The percentage" +
                        " change is based on the previous year’s budget.",
                    id: "2",
                    settings: {},
                    title: 'NREN Budgets per year, in Millions EUR'
                }
                setBudgetMatrixResponse(dataResponse);
            }
        }
    
        const barResponse: BudgetMatrix = budgetMatrixResponse !== undefined
            ? budgetMatrixResponse : empty_bar_response;
        return (
            <div>
                <h1>Data Analysis</h1>
                <Container>
                    <Row>
                        <Col>
                            <Row>
                                <LineGraph data={barResponse.data} />
                            </Row>
                            <Row>{budgetMatrixResponse?.description}</Row>
    
                        </Col>
                        <Col xs={3}>
                            <Accordion defaultActiveKey="0">
                                <Accordion.Item eventKey="0">
                                    <Accordion.Header>Items</Accordion.Header>
                                    <Accordion.Body>
                                        <ListGroup>
                                            {
                                                dataEntrySection?.items.map((item) => (
                                                    <ListGroup.Item key={item.id} action active={item.id == selectedDataEntry} onClick={() => setSelectedDataEntry(item.id)}>{item.title}</ListGroup.Item>
                                                ))
                                            }
                                        </ListGroup>
                                    </Accordion.Body>
                                </Accordion.Item>
                            </Accordion>
                        </Col>
                    </Row>
    
    
                </Container>
            </div>
        );
    }
    
    export default DataAnalysis;