From 492d11c85da70285d3a1c83a2de6fa0b3ddea0b4 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 6 Dec 2021 07:16:19 -0800 Subject: [PATCH] (ui): Initialize endTime and duration from URL params if set --- ui/src/hooks/index.tsx | 9 ++++++- ui/src/views/MetricsView.tsx | 47 +++++++++++++++++++++++++++++++++--- ui/src/views/TasksView.tsx | 7 ++---- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/ui/src/hooks/index.tsx b/ui/src/hooks/index.tsx index cd6184f..7573f77 100644 --- a/ui/src/hooks/index.tsx +++ b/ui/src/hooks/index.tsx @@ -1,4 +1,5 @@ -import { useEffect } from "react"; +import { useEffect, useMemo } from "react"; +import { useLocation } from "react-router-dom"; // usePolling repeatedly calls doFn with a fix time delay specified // by interval (in millisecond). @@ -9,3 +10,9 @@ export function usePolling(doFn: () => void, interval: number) { return () => clearInterval(id); }, [interval, doFn]); } + +// useQuery gets the URL search params from the current URL. +export function useQuery(): URLSearchParams { + const { search } = useLocation(); + return useMemo(() => new URLSearchParams(search), [search]); +} diff --git a/ui/src/views/MetricsView.tsx b/ui/src/views/MetricsView.tsx index 662acf9..f49425e 100644 --- a/ui/src/views/MetricsView.tsx +++ b/ui/src/views/MetricsView.tsx @@ -1,5 +1,7 @@ import React from "react"; import { connect, ConnectedProps } from "react-redux"; +import { useHistory } from "react-router-dom"; +import queryString from "query-string"; import { makeStyles } from "@material-ui/core/styles"; import Container from "@material-ui/core/Container"; import Grid from "@material-ui/core/Grid"; @@ -9,6 +11,7 @@ import { AppState } from "../store"; import QueueSizeMetricsChart from "../components/QueueSizeMetricsChart"; import { currentUnixtime } from "../utils"; import MetricsFetchControls from "../components/MetricsFetchControls"; +import { useQuery } from "../hooks"; const useStyles = makeStyles((theme) => ({ container: { @@ -33,12 +36,48 @@ function mapStateToProps(state: AppState) { const connector = connect(mapStateToProps, { getMetricsAsync }); type Props = ConnectedProps; +const ENDTIME_URL_PARAM_KEY = "end"; +const DURATION_URL_PARAM_KEY = "duration"; + function MetricsView(props: Props) { const classes = useStyles(); + const history = useHistory(); + const query = useQuery(); + + const endTimeStr = query.get(ENDTIME_URL_PARAM_KEY); + const endTime = endTimeStr ? parseFloat(endTimeStr) : currentUnixtime(); // default to now + + const durationStr = query.get(DURATION_URL_PARAM_KEY); + const duration = durationStr ? parseFloat(durationStr) : 60 * 60; // default to 1h + const { pollInterval, getMetricsAsync, data } = props; - const [endTimeSec, setEndTimeSec] = React.useState(currentUnixtime()); - const [durationSec, setDurationSec] = React.useState(60 * 60); // 1h + const [endTimeSec, setEndTimeSec] = React.useState(endTime); + const [durationSec, setDurationSec] = React.useState(duration); + + const handleEndTimeChange = (endTime: number) => { + const urlQuery = { + [ENDTIME_URL_PARAM_KEY]: endTime, + [DURATION_URL_PARAM_KEY]: durationSec, + }; + history.push({ + ...history.location, + search: queryString.stringify(urlQuery), + }); + setEndTimeSec(endTime); + }; + + const handleDurationChange = (duration: number) => { + const urlQuery = { + [ENDTIME_URL_PARAM_KEY]: endTimeSec, + [DURATION_URL_PARAM_KEY]: duration, + }; + history.push({ + ...history.location, + search: queryString.stringify(urlQuery), + }); + setDurationSec(duration); + }; React.useEffect(() => { getMetricsAsync(endTimeSec, durationSec); @@ -51,9 +90,9 @@ function MetricsView(props: Props) {
diff --git a/ui/src/views/TasksView.tsx b/ui/src/views/TasksView.tsx index f6f88e1..b39db74 100644 --- a/ui/src/views/TasksView.tsx +++ b/ui/src/views/TasksView.tsx @@ -6,10 +6,11 @@ import Grid from "@material-ui/core/Grid"; import TasksTable from "../components/TasksTable"; import QueueInfoBanner from "../components/QueueInfoBanner"; import QueueBreadCrumb from "../components/QueueBreadcrumb"; -import { useParams, useLocation } from "react-router-dom"; +import { useParams } from "react-router-dom"; import { listQueuesAsync } from "../actions/queuesActions"; import { AppState } from "../store"; import { QueueDetailsRouteParams } from "../paths"; +import { useQuery } from "../hooks"; function mapStateToProps(state: AppState) { return { @@ -34,10 +35,6 @@ const useStyles = makeStyles((theme) => ({ }, })); -function useQuery(): URLSearchParams { - return new URLSearchParams(useLocation().search); -} - const validStatus = [ "active", "pending",