diff --git a/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx index 6456f73610ac..62c898c3f235 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx @@ -56,7 +56,9 @@ import { UIConfigState } from "../store"; import moment from "moment"; import { StatementDetailsRequest } from "src/api/statementsApi"; import { + getValidOption, TimeScale, + timeScale1hMinOptions, TimeScaleDropdown, toRoundedDateRange, } from "../timeScaleDropdown"; @@ -320,6 +322,14 @@ export class StatementDetails extends React.Component< currentTab: searchParams.get("tab") || "overview", }; this.activateDiagnosticsRef = React.createRef(); + + // In case the user selected a option not available on this page, + // force a selection of a valid option. This is necessary for the case + // where the value 10/30 min is selected on the Metrics page. + const ts = getValidOption(this.props.timeScale, timeScale1hMinOptions); + if (ts !== this.props.timeScale) { + this.props.onTimeScaleChange(ts); + } } static defaultProps: Partial = { @@ -542,6 +552,7 @@ export class StatementDetails extends React.Component< @@ -667,6 +678,7 @@ export class StatementDetails extends React.Component< @@ -805,6 +817,7 @@ export class StatementDetails extends React.Component< diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx index fd8f5c856ddf..f7181fc85b0f 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx @@ -74,6 +74,8 @@ import { TimeScaleDropdown, TimeScale, toDateRange, + timeScale1hMinOptions, + getValidOption, } from "../timeScaleDropdown"; import { commonStyles } from "../common"; @@ -192,6 +194,14 @@ export class StatementsPage extends React.Component< const stateFromHistory = this.getStateFromHistory(); this.state = merge(defaultState, stateFromHistory); this.activateDiagnosticsRef = React.createRef(); + + // In case the user selected a option not available on this page, + // force a selection of a valid option. This is necessary for the case + // where the value 10/30 min is selected on the Metrics page. + const ts = getValidOption(this.props.timeScale, timeScale1hMinOptions); + if (ts !== this.props.timeScale) { + this.changeTimeScale(ts); + } } static defaultProps: Partial = { @@ -658,6 +668,7 @@ export class StatementsPage extends React.Component< diff --git a/pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/timeScaleDropdown.tsx b/pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/timeScaleDropdown.tsx index 06a275687d28..a5c0adb74b3b 100644 --- a/pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/timeScaleDropdown.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/timeScaleDropdown.tsx @@ -12,10 +12,10 @@ import React, { useMemo } from "react"; import moment from "moment"; import classNames from "classnames/bind"; import { - TimeScale, - TimeWindow, ArrowDirection, + TimeScale, TimeScaleOptions, + TimeWindow, } from "./timeScaleTypes"; import TimeFrameControls from "./timeFrameControls"; import RangeSelect, { @@ -263,3 +263,20 @@ export const TimeScaleDropdown: React.FC = ({ ); }; + +// getValidOption check if the option selected is valid. If is valid returns +// the selected option, otherwise returns the first valid option. +export const getValidOption = ( + currentScale: TimeScale, + options: TimeScaleOptions, +): TimeScale => { + if (!(currentScale.key in options)) { + const firstValidKey = Object.keys(options)[0]; + return { + ...options[firstValidKey], + key: firstValidKey, + fixedWindowEnd: false, + }; + } + return currentScale; +}; diff --git a/pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/utils.ts b/pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/utils.ts index ccbee2b96433..748e1500f7bf 100644 --- a/pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/utils.ts +++ b/pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/utils.ts @@ -12,20 +12,10 @@ import moment from "moment"; import { TimeScale, TimeScaleOption, TimeScaleOptions } from "./timeScaleTypes"; /** - * defaultTimeScaleOptions is a preconfigured set of time scales that can be + * timeScale1hMinOptions is a preconfigured set of time scales with 1h minimum that can be * selected by the user. */ -export const defaultTimeScaleOptions: TimeScaleOptions = { - "Past 10 Minutes": { - windowSize: moment.duration(10, "minutes"), - windowValid: moment.duration(10, "seconds"), - sampleSize: moment.duration(10, "seconds"), - }, - "Past 30 Minutes": { - windowSize: moment.duration(30, "minutes"), - windowValid: moment.duration(30, "seconds"), - sampleSize: moment.duration(30, "seconds"), - }, +export const timeScale1hMinOptions: TimeScaleOptions = { "Past 1 Hour": { windowSize: moment.duration(1, "hour"), windowValid: moment.duration(1, "minute"), @@ -73,6 +63,24 @@ export const defaultTimeScaleOptions: TimeScaleOptions = { }, }; +/** + * defaultTimeScaleOptions is a preconfigured set of time scales that can be + * selected by the user. + */ +export const defaultTimeScaleOptions: TimeScaleOptions = { + "Past 10 Minutes": { + windowSize: moment.duration(10, "minutes"), + windowValid: moment.duration(10, "seconds"), + sampleSize: moment.duration(10, "seconds"), + }, + "Past 30 Minutes": { + windowSize: moment.duration(30, "minutes"), + windowValid: moment.duration(30, "seconds"), + sampleSize: moment.duration(30, "seconds"), + }, + ...timeScale1hMinOptions, +}; + export const defaultTimeScaleSelected: TimeScale = { ...defaultTimeScaleOptions["Past 1 Hour"], key: "Past 1 Hour", diff --git a/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx index 912aab586a47..c4eb3f79c610 100644 --- a/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx @@ -58,7 +58,9 @@ import { Transaction } from "src/transactionsTable"; import Long from "long"; import { StatementsRequest } from "../api"; import { + getValidOption, TimeScale, + timeScale1hMinOptions, TimeScaleDropdown, toDateRange, } from "../timeScaleDropdown"; @@ -129,6 +131,14 @@ export class TransactionDetails extends React.Component< }, latestTransactionText: "", }; + + // In case the user selected a option not available on this page, + // force a selection of a valid option. This is necessary for the case + // where the value 10/30 min is selected on the Metrics page. + const ts = getValidOption(this.props.timeScale, timeScale1hMinOptions); + if (ts !== this.props.timeScale) { + this.props.onTimeScaleChange(ts); + } } static defaultProps: Partial = { @@ -237,6 +247,7 @@ export class TransactionDetails extends React.Component< diff --git a/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx b/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx index ed9758742115..5b1aa960adce 100644 --- a/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx @@ -64,6 +64,8 @@ import { TimeScaleDropdown, TimeScale, toDateRange, + timeScale1hMinOptions, + getValidOption, } from "../timeScaleDropdown"; import { InlineAlert } from "@cockroachlabs/ui-components"; import { TransactionViewType } from "./transactionsPageTypes"; @@ -134,6 +136,14 @@ export class TransactionsPage extends React.Component< }; const stateFromHistory = this.getStateFromHistory(); this.state = merge(this.state, stateFromHistory); + + // In case the user selected a option not available on this page, + // force a selection of a valid option. This is necessary for the case + // where the value 10/30 min is selected on the Metrics page. + const ts = getValidOption(this.props.timeScale, timeScale1hMinOptions); + if (ts !== this.props.timeScale) { + this.changeTimeScale(ts); + } } getStateFromHistory = (): Partial => { @@ -408,6 +418,7 @@ export class TransactionsPage extends React.Component<