Source

pages/SingleChartPage.jsx

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

/**
 * 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 SingleTimeSeries} 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 SingleChartPage = () => {
    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]})
    
    let body = JSON.stringify({
            "start": state.startTime,
            "end": state.endTime
            });
    
    const {isLoading, isError, data} = useFetch(location.state.url, 'POST', body, null, state.startTime, state.endTime, location.state.type);

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

    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>
                })
            }
            <SingleChartPanel
                description={location.state.description}
                isBinary={location.state.isBinary}
                xAxesLabelString={location.state.xAxesLabelString}
                yAxesLabelString={location.state.yAxesLabelString}
                type={location.state.type}
                dataSet={data}/>
        </div>
    );
}

const SingleChartPanel = ({description, isBinary, xAxesLabelString, yAxesLabelString, dataSet, type}) => {
    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] ?? data['value']
        }
    });
    return chartData;
}


export default SingleChartPage