Source

pages/MultiChartPage.jsx

import React, { useState } from 'react'
import { useHistory, useLocation} from 'react-router';
import useMultipleFetch from '../hooks/use-multiple-fetch';
import { useTranslation } from 'react-i18next';
import { Line } from 'react-chartjs-2'
import './pages.css'
import useInterval from '../hooks/use-interval';

/**
 * This is the page used to display more details of the history of values of a particular sensor or Thing. 
 * It is shown when a {@link MultipleTimeSeries} in any {@link ThingTile} is clicked.
 * It contains buttons for selecting how much interval of history should be shown. Either for
 * one day, one month or one year and retrieves the value history for the thing that corresponds to the
 * selected time interval. 
 * It can only be viewed by clicking on a {@link MultipleTimeSeries} otherwise the page 
 * redirects to an {@link ErrorPage} instead.
 * 
 * @category Pages
 * @component
 */
const MultiChartPage = () => {
    const { t, } = useTranslation();
    const location = useLocation();
    const history = useHistory();
    if (location.state === undefined) {
        history.push('/error');
    }
    const intervals = [t("one_day"), t("one_month"), t("one_year")]
    const intervalValues = [86400, 2592000, 31104000]
    let now = parseInt(Date.now()/1000);
    const [state, setState] = useState({intervalIndex: 0, endTime: now, startTime: now - intervalValues[0], propertyIndex: 0})
    
    let body = JSON.stringify({
            "start": state.startTime,
            "end": state.endTime
            });
    
    const {isLoading, isError, data} = useMultipleFetch(location.state.urlList, 'POST', body, null, state.startTime, state.endTime);
    

    const handleIntervalChange = (index) => {
        let now = parseInt(Date.now()/1000)
        setState({
            intervalIndex: index, 
            endTime: now, 
            startTime: now - intervalValues[index],
            propertyIndex: 0
        })
    }

    if (isLoading){
        return <div className="ml-3">{t("loading")}...</div>;
    }

    if (isError){
        return <div className="ml-3">{t("error")}...</div>;
    }

    console.log("data: " + data)

    return (
        <div className="detailChart p-2">
            {
                intervals.map((interval, index) => {
                    return <button key={index}
                                className={`btn btn-primary text-white rounded-0 border border-primary
                                            ${index === state.intervalIndex && 'bg-white text-primary'}`}
                                onClick={() => handleIntervalChange(index)}>
                                {interval}
                           </button>
                })
            }
            <MultiChartPanel
                description={location.state.description}
                isBinaryList={location.state.isBinaryList}
                xAxesLabelStringList={location.state.xAxesLabelStringList}
                yAxesLabelStringList={location.state.yAxesLabelStringList}
                typeList={location.state.typeList}
                dataSetList={data}/>
        </div>
    );
}

const MultiChartPanel = ({description, isBinaryList, xAxesLabelStringList, yAxesLabelStringList, dataSetList, typeList}) => {
    const [propertyIndex, setPropertyIndex] = useState(0)
    
    const isBinary = isBinaryList[propertyIndex]
    const xAxesLabelString = xAxesLabelStringList[propertyIndex]
    const yAxesLabelString = yAxesLabelStringList[propertyIndex]
    const dataSet = dataSetList[propertyIndex]
    const type = typeList[propertyIndex]

    useInterval(() => {
        setPropertyIndex((propertyIndex + 1) % dataSetList.length)
    }, 10000)

    const data = {
        labels: [],
        datasets: [
            {
                type: 'line',
                backgroundColor: "#C96D4288", // Options: 00555588 C96D4288 8E9D4DBB
                borderColor: "#4e73df",
                fill: true,
                borderWidth: 2,
                data: Array.isArray(dataSet) ? getChartData(dataSet, type): null,
                steppedLine: isBinary,
                pointRadius: 0
            }
        ]
    }

    const options = {
        animation: false,
        responsive : true,
        maintainAspectRatio: false,
        title:{
            display:true,
            text: description
        },
        legend:{
            display:false,
        },
        elements: {
            line: {
                tension: 0
            }
        },
        scales: {
		    yAxes: [{
                ticks: {
                    fontSize: 8
                },
		    	scaleLabel : {
		   		display: true,
		   		labelString: yAxesLabelString
		    	}
		    }],
		    xAxes: [{
                ticks: {
                    fontSize: 8
                },
                type: 'time',
                distribution: 'linear',
		    	scaleLabel : {
                    display: true,
                    labelString: xAxesLabelString
		    	}
		    }]
		}

    }
    return (
        <div className="w-100 h-100 p-2">
            <Line data={data} options={options}/>
        </div>
    )
}

const getChartData = (dataSet, type) => {
    const chartData = dataSet.map((data) => {
        return {
            x: data['time'],
            y: data[type]
        }
    });
    return chartData;
}


export default MultiChartPage