diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/Cookie.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/Cookie.java index 0274b1147..e723139a7 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/Cookie.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/auth/Cookie.java @@ -24,9 +24,11 @@ public class Cookie { private final String value; public Cookie(String rawRepresentation) { - String[] split = StringUtils.split(rawRepresentation, "=", 2); - name = split[0]; - value = split[1]; + this(StringUtils.split(rawRepresentation, "=", 2)); + } + + private Cookie(String[] splitRawRepresentation) { + this(splitRawRepresentation[0], splitRawRepresentation[1]); } public Cookie(String name, String value) { diff --git a/Plan/react/dashboard/src/components/cards/query/QueryOptionsCard.js b/Plan/react/dashboard/src/components/cards/query/QueryOptionsCard.js index 33a9de590..fefeaeb23 100644 --- a/Plan/react/dashboard/src/components/cards/query/QueryOptionsCard.js +++ b/Plan/react/dashboard/src/components/cards/query/QueryOptionsCard.js @@ -1,4 +1,4 @@ -import React, {useState} from 'react'; +import React, {useCallback, useEffect, useState} from 'react'; import {Card, Col, Row} from "react-bootstrap-v5"; import {useTranslation} from "react-i18next"; import {useDataRequest} from "../../../hooks/dataFetchHook"; @@ -9,6 +9,24 @@ import DateInputField from "../../input/DateInputField"; import TimeInputField from "../../input/TimeInputField"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; import {faSearch} from "@fortawesome/free-solid-svg-icons"; +import PlayersOnlineGraph from "../../graphs/PlayersOnlineGraph"; +import Highcharts from "highcharts/highstock"; + +const parseTime = (dateString, timeString) => { + const d = dateString.match( + /^(0\d|\d{2})[\/|\-]?(0\d|\d{2})[\/|\-]?(\d{4,5})$/ + ); + const t = timeString.match(/^(0\d|\d{2}):?(0\d|\d{2})$/); + + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date + const parsedDay = Number(d[1]); + const parsedMonth = Number(d[2]) - 1; // 0=January, 11=December + const parsedYear = Number(d[3]); + let hour = Number(t[1]); + let minute = Number(t[2]); + const date = new Date(parsedYear, parsedMonth, parsedDay, hour, minute); + return date.getTime() - (date.getTimezoneOffset() * 60000); +}; const QueryOptionsCard = () => { const {t} = useTranslation(); @@ -17,12 +35,48 @@ const QueryOptionsCard = () => { const [fromTime, setFromTime] = useState(undefined); const [toDate, setToDate] = useState(undefined); const [toTime, setToTime] = useState(undefined); - const [invalidFields, setInvalidFields] = useState([]); const setAsInvalid = id => setInvalidFields([...invalidFields, id]); const setAsValid = id => setInvalidFields(invalidFields.filter(invalid => id !== invalid)); + const [extremes, setExtremes] = useState(undefined); + const updateExtremes = useCallback(() => { + if (invalidFields.length || !options) return; + const newMin = parseTime( + fromDate ? fromDate : options.view.afterDate, + fromTime ? fromTime : options.view.afterTime + ); + const newMax = parseTime( + toDate ? toDate : options.view.beforeDate, + toTime ? toTime : options.view.beforeTime + ); + setExtremes({ + min: newMin, + max: newMax + }); + }, [fromDate, fromTime, toDate, toTime, invalidFields]); + useEffect(updateExtremes, [invalidFields]); + + const onSetExtremes = useCallback((event) => { + if (event && (event.trigger === "navigator" || event.trigger === 'rangeSelectorButton')) { + const afterDate = Highcharts.dateFormat('%d/%m/%Y', event.min); + const afterTime = Highcharts.dateFormat('%H:%M', event.min); + const beforeDate = Highcharts.dateFormat('%d/%m/%Y', event.max); + const beforeTime = Highcharts.dateFormat('%H:%M', event.max); + setFromDate(afterDate); + setFromTime(afterTime); + setToDate(beforeDate); + setToTime(beforeTime); + } + }, [setFromTime, setFromDate, setToTime, setToDate]); + const {data: options, loadingError} = useDataRequest(fetchFilters, []); + const [graphData, setGraphData] = useState(undefined); + useEffect(() => { + if (options) { + setGraphData({playersOnline: options.viewPoints, color: '#9E9E9E'}) + } + }, [options, setGraphData]); if (loadingError) return if (!options) return ( @@ -31,7 +85,7 @@ const QueryOptionsCard = () => { ) - const view = options.view; + const view = options?.view; return ( @@ -39,7 +93,7 @@ const QueryOptionsCard = () => { - @@ -60,7 +114,7 @@ const QueryOptionsCard = () => { /> - @@ -81,6 +135,16 @@ const QueryOptionsCard = () => { /> + + + + +