diff --git a/web/ui/mantine-ui/package.json b/web/ui/mantine-ui/package.json index f9999a247..2fbefe050 100644 --- a/web/ui/mantine-ui/package.json +++ b/web/ui/mantine-ui/package.json @@ -16,6 +16,7 @@ "@codemirror/lint": "^6.5.0", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.24.0", + "@floating-ui/dom": "^1.6.7", "@lezer/common": "^1.2.1", "@lezer/highlight": "^1.2.0", "@mantine/code-highlight": "^7.6.1", diff --git a/web/ui/mantine-ui/src/pages/query/ColorPool.ts b/web/ui/mantine-ui/src/pages/query/ColorPool.ts new file mode 100644 index 000000000..1dd70928c --- /dev/null +++ b/web/ui/mantine-ui/src/pages/query/ColorPool.ts @@ -0,0 +1,935 @@ +export const colorPool = [ + "#008000", + "#008080", + "#800000", + "#800080", + "#808000", + "#808080", + "#0000c0", + "#008040", + "#0080c0", + "#800040", + "#8000c0", + "#808040", + "#8080c0", + "#00c000", + "#00c080", + "#804000", + "#804080", + "#80c000", + "#80c080", + "#0040c0", + "#00c040", + "#00c0c0", + "#804040", + "#8040c0", + "#80c040", + "#80c0c0", + "#408000", + "#408080", + "#c00000", + "#c00080", + "#c08000", + "#c08080", + "#4000c0", + "#408040", + "#4080c0", + "#c00040", + "#c000c0", + "#c08040", + "#c080c0", + "#404000", + "#404080", + "#40c000", + "#40c080", + "#c04000", + "#c04080", + "#c0c000", + "#c0c080", + "#404040", + "#4040c0", + "#40c040", + "#40c0c0", + "#c04040", + "#c040c0", + "#c0c040", + "#0000a0", + "#008020", + "#0080a0", + "#800020", + "#8000a0", + "#808020", + "#8080a0", + "#0000e0", + "#008060", + "#0080e0", + "#800060", + "#8000e0", + "#808060", + "#8080e0", + "#0040a0", + "#00c020", + "#00c0a0", + "#804020", + "#8040a0", + "#80c020", + "#80c0a0", + "#0040e0", + "#00c060", + "#00c0e0", + "#804060", + "#8040e0", + "#80c060", + "#80c0e0", + "#4000a0", + "#408020", + "#4080a0", + "#c00020", + "#c000a0", + "#c08020", + "#c080a0", + "#4000e0", + "#408060", + "#4080e0", + "#c00060", + "#c000e0", + "#c08060", + "#c080e0", + "#404020", + "#4040a0", + "#40c020", + "#40c0a0", + "#c04020", + "#c040a0", + "#c0c020", + "#c0c0a0", + "#404060", + "#4040e0", + "#40c060", + "#40c0e0", + "#c04060", + "#c040e0", + "#c0c060", + "#00a000", + "#00a080", + "#802000", + "#802080", + "#80a000", + "#80a080", + "#0020c0", + "#00a040", + "#00a0c0", + "#802040", + "#8020c0", + "#80a040", + "#80a0c0", + "#006000", + "#006080", + "#00e000", + "#00e080", + "#806000", + "#806080", + "#80e000", + "#80e080", + "#006040", + "#0060c0", + "#00e040", + "#00e0c0", + "#806040", + "#8060c0", + "#80e040", + "#80e0c0", + "#40a000", + "#40a080", + "#c02000", + "#c02080", + "#c0a000", + "#c0a080", + "#4020c0", + "#40a040", + "#40a0c0", + "#c02040", + "#c020c0", + "#c0a040", + "#c0a0c0", + "#406000", + "#406080", + "#40e000", + "#40e080", + "#c06000", + "#c06080", + "#c0e000", + "#c0e080", + "#406040", + "#4060c0", + "#40e040", + "#40e0c0", + "#c06040", + "#c060c0", + "#c0e040", + "#c0e0c0", + "#0020a0", + "#00a020", + "#00a0a0", + "#802020", + "#8020a0", + "#80a020", + "#80a0a0", + "#0020e0", + "#00a060", + "#00a0e0", + "#802060", + "#8020e0", + "#80a060", + "#80a0e0", + "#006020", + "#0060a0", + "#00e020", + "#00e0a0", + "#806020", + "#8060a0", + "#80e020", + "#80e0a0", + "#006060", + "#0060e0", + "#00e060", + "#00e0e0", + "#806060", + "#8060e0", + "#80e060", + "#80e0e0", + "#4020a0", + "#40a020", + "#40a0a0", + "#c02020", + "#c020a0", + "#c0a020", + "#c0a0a0", + "#4020e0", + "#40a060", + "#40a0e0", + "#c02060", + "#c020e0", + "#c0a060", + "#c0a0e0", + "#406020", + "#4060a0", + "#40e020", + "#40e0a0", + "#c06020", + "#c060a0", + "#c0e020", + "#c0e0a0", + "#406060", + "#4060e0", + "#40e060", + "#40e0e0", + "#c06060", + "#c060e0", + "#c0e060", + "#208000", + "#208080", + "#a00000", + "#a00080", + "#a08000", + "#a08080", + "#208040", + "#2080c0", + "#a00040", + "#a000c0", + "#a08040", + "#a080c0", + "#204080", + "#20c000", + "#20c080", + "#a04000", + "#a04080", + "#a0c000", + "#a0c080", + "#2040c0", + "#20c040", + "#20c0c0", + "#a04040", + "#a040c0", + "#a0c040", + "#a0c0c0", + "#608000", + "#608080", + "#e00000", + "#e00080", + "#e08000", + "#e08080", + "#6000c0", + "#608040", + "#6080c0", + "#e00040", + "#e000c0", + "#e08040", + "#e080c0", + "#604080", + "#60c000", + "#60c080", + "#e04000", + "#e04080", + "#e0c000", + "#e0c080", + "#604040", + "#6040c0", + "#60c040", + "#60c0c0", + "#e04040", + "#e040c0", + "#e0c040", + "#e0c0c0", + "#208020", + "#2080a0", + "#a00020", + "#a000a0", + "#a08020", + "#a080a0", + "#2000e0", + "#208060", + "#2080e0", + "#a00060", + "#a000e0", + "#a08060", + "#a080e0", + "#2040a0", + "#20c020", + "#20c0a0", + "#a04020", + "#a040a0", + "#a0c020", + "#2040e0", + "#20c060", + "#20c0e0", + "#a04060", + "#a040e0", + "#a0c060", + "#a0c0e0", + "#6000a0", + "#608020", + "#6080a0", + "#e00020", + "#e000a0", + "#e08020", + "#e080a0", + "#6000e0", + "#608060", + "#6080e0", + "#e00060", + "#e000e0", + "#e08060", + "#e080e0", + "#604020", + "#6040a0", + "#60c020", + "#60c0a0", + "#e04020", + "#e040a0", + "#e0c020", + "#e0c0a0", + "#604060", + "#6040e0", + "#60c060", + "#60c0e0", + "#e04060", + "#e040e0", + "#e0c060", + "#e0c0e0", + "#20a000", + "#20a080", + "#a02000", + "#a02080", + "#a0a000", + "#a0a080", + "#2020c0", + "#20a040", + "#20a0c0", + "#a02040", + "#a020c0", + "#a0a040", + "#a0a0c0", + "#206000", + "#206080", + "#20e000", + "#20e080", + "#a06000", + "#a06080", + "#a0e000", + "#a0e080", + "#206040", + "#2060c0", + "#20e040", + "#20e0c0", + "#a06040", + "#a060c0", + "#a0e040", + "#a0e0c0", + "#602080", + "#60a000", + "#60a080", + "#e02000", + "#e02080", + "#e0a000", + "#e0a080", + "#6020c0", + "#60a040", + "#60a0c0", + "#e02040", + "#e020c0", + "#e0a040", + "#e0a0c0", + "#606000", + "#606080", + "#60e000", + "#60e080", + "#e06000", + "#e06080", + "#e0e000", + "#e0e080", + "#606040", + "#6060c0", + "#60e040", + "#60e0c0", + "#e06040", + "#e060c0", + "#e0e040", + "#e0e0c0", + "#20a020", + "#20a0a0", + "#a02020", + "#a020a0", + "#a0a020", + "#a0a0a0", + "#2020e0", + "#20a060", + "#20a0e0", + "#a02060", + "#a020e0", + "#a0a060", + "#a0a0e0", + "#206020", + "#2060a0", + "#20e020", + "#20e0a0", + "#a06020", + "#a060a0", + "#a0e020", + "#a0e0a0", + "#206060", + "#2060e0", + "#20e060", + "#20e0e0", + "#a06060", + "#a060e0", + "#a0e060", + "#a0e0e0", + "#6020a0", + "#60a020", + "#60a0a0", + "#e02020", + "#e020a0", + "#e0a020", + "#e0a0a0", + "#602060", + "#6020e0", + "#60a060", + "#60a0e0", + "#e02060", + "#e020e0", + "#e0a060", + "#e0a0e0", + "#606020", + "#6060a0", + "#60e020", + "#60e0a0", + "#e06020", + "#e060a0", + "#e0e020", + "#e0e0a0", + "#606060", + "#6060e0", + "#60e060", + "#60e0e0", + "#e06060", + "#e060e0", + "#e0e060", + "#008010", + "#008090", + "#800010", + "#800090", + "#808010", + "#808090", + "#0000d0", + "#008050", + "#0080d0", + "#800050", + "#8000d0", + "#808050", + "#8080d0", + "#004010", + "#004090", + "#00c010", + "#00c090", + "#804010", + "#804090", + "#80c010", + "#80c090", + "#004050", + "#0040d0", + "#00c050", + "#00c0d0", + "#804050", + "#8040d0", + "#80c050", + "#80c0d0", + "#400090", + "#408010", + "#408090", + "#c00010", + "#c00090", + "#c08010", + "#c08090", + "#4000d0", + "#408050", + "#4080d0", + "#c00050", + "#c000d0", + "#c08050", + "#c080d0", + "#404010", + "#404090", + "#40c010", + "#40c090", + "#c04010", + "#c04090", + "#c0c010", + "#c0c090", + "#404050", + "#4040d0", + "#40c050", + "#40c0d0", + "#c04050", + "#c040d0", + "#c0c050", + "#0000b0", + "#008030", + "#0080b0", + "#800030", + "#8000b0", + "#808030", + "#8080b0", + "#0000f0", + "#008070", + "#0080f0", + "#800070", + "#8000f0", + "#808070", + "#8080f0", + "#004030", + "#0040b0", + "#00c030", + "#00c0b0", + "#804030", + "#8040b0", + "#80c030", + "#80c0b0", + "#004070", + "#0040f0", + "#00c070", + "#00c0f0", + "#804070", + "#8040f0", + "#80c070", + "#80c0f0", + "#4000b0", + "#408030", + "#4080b0", + "#c00030", + "#c000b0", + "#c08030", + "#c080b0", + "#400070", + "#4000f0", + "#408070", + "#4080f0", + "#c00070", + "#c000f0", + "#c08070", + "#c080f0", + "#404030", + "#4040b0", + "#40c030", + "#40c0b0", + "#c04030", + "#c040b0", + "#c0c030", + "#c0c0b0", + "#404070", + "#4040f0", + "#40c070", + "#40c0f0", + "#c04070", + "#c040f0", + "#c0c070", + "#c0c0f0", + "#002090", + "#00a010", + "#00a090", + "#802010", + "#802090", + "#80a010", + "#80a090", + "#0020d0", + "#00a050", + "#00a0d0", + "#802050", + "#8020d0", + "#80a050", + "#80a0d0", + "#006010", + "#006090", + "#00e010", + "#00e090", + "#806010", + "#806090", + "#80e010", + "#80e090", + "#006050", + "#0060d0", + "#00e050", + "#00e0d0", + "#806050", + "#8060d0", + "#80e050", + "#80e0d0", + "#402090", + "#40a010", + "#40a090", + "#c02010", + "#c02090", + "#c0a010", + "#c0a090", + "#402050", + "#4020d0", + "#40a050", + "#40a0d0", + "#c02050", + "#c020d0", + "#c0a050", + "#c0a0d0", + "#406010", + "#406090", + "#40e010", + "#40e090", + "#c06010", + "#c06090", + "#c0e010", + "#c0e090", + "#406050", + "#4060d0", + "#40e050", + "#40e0d0", + "#c06050", + "#c060d0", + "#c0e050", + "#c0e0d0", + "#0020b0", + "#00a030", + "#00a0b0", + "#802030", + "#8020b0", + "#80a030", + "#80a0b0", + "#0020f0", + "#00a070", + "#00a0f0", + "#802070", + "#8020f0", + "#80a070", + "#80a0f0", + "#006030", + "#0060b0", + "#00e030", + "#00e0b0", + "#806030", + "#8060b0", + "#80e030", + "#80e0b0", + "#006070", + "#0060f0", + "#00e070", + "#00e0f0", + "#806070", + "#8060f0", + "#80e070", + "#80e0f0", + "#4020b0", + "#40a030", + "#40a0b0", + "#c02030", + "#c020b0", + "#c0a030", + "#c0a0b0", + "#4020f0", + "#40a070", + "#40a0f0", + "#c02070", + "#c020f0", + "#c0a070", + "#c0a0f0", + "#406030", + "#4060b0", + "#40e030", + "#40e0b0", + "#c06030", + "#c060b0", + "#c0e030", + "#c0e0b0", + "#406070", + "#4060f0", + "#40e070", + "#40e0f0", + "#c06070", + "#c060f0", + "#c0e070", + "#208010", + "#208090", + "#a00010", + "#a00090", + "#a08010", + "#a08090", + "#2000d0", + "#208050", + "#2080d0", + "#a00050", + "#a000d0", + "#a08050", + "#a080d0", + "#204010", + "#204090", + "#20c010", + "#20c090", + "#a04010", + "#a04090", + "#a0c010", + "#a0c090", + "#204050", + "#2040d0", + "#20c050", + "#20c0d0", + "#a04050", + "#a040d0", + "#a0c050", + "#a0c0d0", + "#600090", + "#608010", + "#608090", + "#e00010", + "#e00090", + "#e08010", + "#e08090", + "#600050", + "#6000d0", + "#608050", + "#6080d0", + "#e00050", + "#e000d0", + "#e08050", + "#e080d0", + "#604010", + "#604090", + "#60c010", + "#60c090", + "#e04010", + "#e04090", + "#e0c010", + "#e0c090", + "#604050", + "#6040d0", + "#60c050", + "#60c0d0", + "#e04050", + "#e040d0", + "#e0c050", + "#e0c0d0", + "#2000b0", + "#208030", + "#2080b0", + "#a00030", + "#a000b0", + "#a08030", + "#a080b0", + "#2000f0", + "#208070", + "#2080f0", + "#a00070", + "#a000f0", + "#a08070", + "#a080f0", + "#204030", + "#2040b0", + "#20c030", + "#20c0b0", + "#a04030", + "#a040b0", + "#a0c030", + "#a0c0b0", + "#204070", + "#2040f0", + "#20c070", + "#20c0f0", + "#a04070", + "#a040f0", + "#a0c070", + "#a0c0f0", + "#6000b0", + "#608030", + "#6080b0", + "#e00030", + "#e000b0", + "#e08030", + "#e080b0", + "#600070", + "#6000f0", + "#608070", + "#e00070", + "#e000f0", + "#e08070", + "#e080f0", + "#604030", + "#6040b0", + "#60c030", + "#60c0b0", + "#e04030", + "#e040b0", + "#e0c030", + "#e0c0b0", + "#604070", + "#6040f0", + "#60c070", + "#60c0f0", + "#e04070", + "#e040f0", + "#e0c070", + "#e0c0f0", + "#20a010", + "#20a090", + "#a02010", + "#a02090", + "#a0a010", + "#a0a090", + "#2020d0", + "#20a050", + "#20a0d0", + "#a02050", + "#a020d0", + "#a0a050", + "#a0a0d0", + "#206010", + "#206090", + "#20e010", + "#20e090", + "#a06010", + "#a06090", + "#a0e010", + "#a0e090", + "#206050", + "#2060d0", + "#20e050", + "#20e0d0", + "#a06050", + "#a060d0", + "#a0e050", + "#a0e0d0", + "#602090", + "#60a010", + "#60a090", + "#e02010", + "#e02090", + "#e0a010", + "#e0a090", + "#602050", + "#6020d0", + "#60a050", + "#60a0d0", + "#e02050", + "#e020d0", + "#e0a050", + "#e0a0d0", + "#606010", + "#606090", + "#60e010", + "#60e090", + "#e06010", + "#e06090", + "#e0e010", + "#e0e090", + "#606050", + "#6060d0", + "#60e050", + "#60e0d0", + "#e06050", + "#e060d0", + "#e0e050", + "#2020b0", + "#20a030", + "#20a0b0", + "#a02030", + "#a020b0", + "#a0a030", + "#a0a0b0", + "#2020f0", + "#20a070", + "#20a0f0", + "#a02070", + "#a020f0", + "#a0a070", + "#a0a0f0", + "#206030", + "#2060b0", + "#20e030", + "#20e0b0", + "#a06030", + "#a060b0", + "#a0e030", + "#a0e0b0", + "#206070", + "#2060f0", + "#20e070", + "#20e0f0", + "#a06070", + "#a060f0", + "#a0e070", + "#a0e0f0", + "#6020b0", + "#60a030", + "#60a0b0", + "#e02030", + "#e020b0", + "#e0a030", + "#e0a0b0", + "#6020f0", + "#60a070", + "#60a0f0", + "#e02070", + "#e020f0", + "#e0a070", + "#e0a0f0", + "#606030", + "#6060b0", + "#60e030", + "#60e0b0", + "#e06030", + "#e060b0", + "#e0e030", + "#e0e0b0", + "#606070", + "#6060f0", + "#60e070", + "#60e0f0", + "#e06070", + "#e060f0", + "#e0e070", +]; diff --git a/web/ui/mantine-ui/src/pages/query/ExpressionInput.tsx b/web/ui/mantine-ui/src/pages/query/ExpressionInput.tsx index cbb4823b2..4d2eff304 100644 --- a/web/ui/mantine-ui/src/pages/query/ExpressionInput.tsx +++ b/web/ui/mantine-ui/src/pages/query/ExpressionInput.tsx @@ -107,6 +107,10 @@ export class HistoryCompleteStrategy implements CompleteStrategy { } } +// This is just a placeholder until query history is implemented, so disable the linter warning. +// eslint-disable-next-line react-hooks/exhaustive-deps +const queryHistory = [] as string[]; + interface ExpressionInputProps { initialExpr: string; metricNames: string[]; @@ -166,10 +170,6 @@ const ExpressionInput: FC = ({ } }, [formatResult, formatError]); - // This is just a placeholder until query history is implemented, so disable the linter warning. - // eslint-disable-next-line react-hooks/exhaustive-deps - const queryHistory = [] as string[]; - // (Re)initialize editor based on settings / setting changes. useEffect(() => { // Build the dynamic part of the config. @@ -205,7 +205,7 @@ const ExpressionInput: FC = ({ size="lg" variant="transparent" color="gray" - aria-label="Decrease range" + aria-label="Show query options" > diff --git a/web/ui/mantine-ui/src/pages/query/Graph.tsx b/web/ui/mantine-ui/src/pages/query/Graph.tsx index 33b3b9b7e..39ec28fc9 100644 --- a/web/ui/mantine-ui/src/pages/query/Graph.tsx +++ b/web/ui/mantine-ui/src/pages/query/Graph.tsx @@ -1,16 +1,23 @@ -import { FC, useEffect, useId } from "react"; +import { FC, useEffect, useId, useLayoutEffect, useState } from "react"; import { Alert, Skeleton, Box, LoadingOverlay } from "@mantine/core"; import { IconAlertTriangle, IconInfoCircle } from "@tabler/icons-react"; -import { InstantQueryResult } from "../../api/responseTypes/query"; +import { + InstantQueryResult, + RangeSamples, +} from "../../api/responseTypes/query"; import { useAPIQuery } from "../../api/api"; import classes from "./Graph.module.css"; import { GraphDisplayMode } from "../../state/queryPageSlice"; import { formatSeries } from "../../lib/formatSeries"; -import uPlot from "uplot"; +import uPlot, { Series } from "uplot"; import UplotReact from "uplot-react"; import "uplot/dist/uPlot.min.css"; import "./uplot.css"; import { useElementSize } from "@mantine/hooks"; +import { formatTimestamp } from "../../lib/formatTime"; +import { computePosition, shift, flip, offset, Axis } from "@floating-ui/dom"; +import { colorPool } from "./ColorPool"; +import UPlotChart, { UPlotChartProps, UPlotChartRange } from "./UPlotChart"; export interface GraphProps { expr: string; @@ -20,974 +27,68 @@ export interface GraphProps { showExemplars: boolean; displayMode: GraphDisplayMode; retriggerIdx: number; + onSelectRange: (start: number, end: number) => void; } -export const colorPool = [ - "#008000", - "#008080", - "#800000", - "#800080", - "#808000", - "#808080", - "#0000c0", - "#008040", - "#0080c0", - "#800040", - "#8000c0", - "#808040", - "#8080c0", - "#00c000", - "#00c080", - "#804000", - "#804080", - "#80c000", - "#80c080", - "#0040c0", - "#00c040", - "#00c0c0", - "#804040", - "#8040c0", - "#80c040", - "#80c0c0", - "#408000", - "#408080", - "#c00000", - "#c00080", - "#c08000", - "#c08080", - "#4000c0", - "#408040", - "#4080c0", - "#c00040", - "#c000c0", - "#c08040", - "#c080c0", - "#404000", - "#404080", - "#40c000", - "#40c080", - "#c04000", - "#c04080", - "#c0c000", - "#c0c080", - "#404040", - "#4040c0", - "#40c040", - "#40c0c0", - "#c04040", - "#c040c0", - "#c0c040", - "#0000a0", - "#008020", - "#0080a0", - "#800020", - "#8000a0", - "#808020", - "#8080a0", - "#0000e0", - "#008060", - "#0080e0", - "#800060", - "#8000e0", - "#808060", - "#8080e0", - "#0040a0", - "#00c020", - "#00c0a0", - "#804020", - "#8040a0", - "#80c020", - "#80c0a0", - "#0040e0", - "#00c060", - "#00c0e0", - "#804060", - "#8040e0", - "#80c060", - "#80c0e0", - "#4000a0", - "#408020", - "#4080a0", - "#c00020", - "#c000a0", - "#c08020", - "#c080a0", - "#4000e0", - "#408060", - "#4080e0", - "#c00060", - "#c000e0", - "#c08060", - "#c080e0", - "#404020", - "#4040a0", - "#40c020", - "#40c0a0", - "#c04020", - "#c040a0", - "#c0c020", - "#c0c0a0", - "#404060", - "#4040e0", - "#40c060", - "#40c0e0", - "#c04060", - "#c040e0", - "#c0c060", - "#00a000", - "#00a080", - "#802000", - "#802080", - "#80a000", - "#80a080", - "#0020c0", - "#00a040", - "#00a0c0", - "#802040", - "#8020c0", - "#80a040", - "#80a0c0", - "#006000", - "#006080", - "#00e000", - "#00e080", - "#806000", - "#806080", - "#80e000", - "#80e080", - "#006040", - "#0060c0", - "#00e040", - "#00e0c0", - "#806040", - "#8060c0", - "#80e040", - "#80e0c0", - "#40a000", - "#40a080", - "#c02000", - "#c02080", - "#c0a000", - "#c0a080", - "#4020c0", - "#40a040", - "#40a0c0", - "#c02040", - "#c020c0", - "#c0a040", - "#c0a0c0", - "#406000", - "#406080", - "#40e000", - "#40e080", - "#c06000", - "#c06080", - "#c0e000", - "#c0e080", - "#406040", - "#4060c0", - "#40e040", - "#40e0c0", - "#c06040", - "#c060c0", - "#c0e040", - "#c0e0c0", - "#0020a0", - "#00a020", - "#00a0a0", - "#802020", - "#8020a0", - "#80a020", - "#80a0a0", - "#0020e0", - "#00a060", - "#00a0e0", - "#802060", - "#8020e0", - "#80a060", - "#80a0e0", - "#006020", - "#0060a0", - "#00e020", - "#00e0a0", - "#806020", - "#8060a0", - "#80e020", - "#80e0a0", - "#006060", - "#0060e0", - "#00e060", - "#00e0e0", - "#806060", - "#8060e0", - "#80e060", - "#80e0e0", - "#4020a0", - "#40a020", - "#40a0a0", - "#c02020", - "#c020a0", - "#c0a020", - "#c0a0a0", - "#4020e0", - "#40a060", - "#40a0e0", - "#c02060", - "#c020e0", - "#c0a060", - "#c0a0e0", - "#406020", - "#4060a0", - "#40e020", - "#40e0a0", - "#c06020", - "#c060a0", - "#c0e020", - "#c0e0a0", - "#406060", - "#4060e0", - "#40e060", - "#40e0e0", - "#c06060", - "#c060e0", - "#c0e060", - "#208000", - "#208080", - "#a00000", - "#a00080", - "#a08000", - "#a08080", - "#208040", - "#2080c0", - "#a00040", - "#a000c0", - "#a08040", - "#a080c0", - "#204080", - "#20c000", - "#20c080", - "#a04000", - "#a04080", - "#a0c000", - "#a0c080", - "#2040c0", - "#20c040", - "#20c0c0", - "#a04040", - "#a040c0", - "#a0c040", - "#a0c0c0", - "#608000", - "#608080", - "#e00000", - "#e00080", - "#e08000", - "#e08080", - "#6000c0", - "#608040", - "#6080c0", - "#e00040", - "#e000c0", - "#e08040", - "#e080c0", - "#604080", - "#60c000", - "#60c080", - "#e04000", - "#e04080", - "#e0c000", - "#e0c080", - "#604040", - "#6040c0", - "#60c040", - "#60c0c0", - "#e04040", - "#e040c0", - "#e0c040", - "#e0c0c0", - "#208020", - "#2080a0", - "#a00020", - "#a000a0", - "#a08020", - "#a080a0", - "#2000e0", - "#208060", - "#2080e0", - "#a00060", - "#a000e0", - "#a08060", - "#a080e0", - "#2040a0", - "#20c020", - "#20c0a0", - "#a04020", - "#a040a0", - "#a0c020", - "#2040e0", - "#20c060", - "#20c0e0", - "#a04060", - "#a040e0", - "#a0c060", - "#a0c0e0", - "#6000a0", - "#608020", - "#6080a0", - "#e00020", - "#e000a0", - "#e08020", - "#e080a0", - "#6000e0", - "#608060", - "#6080e0", - "#e00060", - "#e000e0", - "#e08060", - "#e080e0", - "#604020", - "#6040a0", - "#60c020", - "#60c0a0", - "#e04020", - "#e040a0", - "#e0c020", - "#e0c0a0", - "#604060", - "#6040e0", - "#60c060", - "#60c0e0", - "#e04060", - "#e040e0", - "#e0c060", - "#e0c0e0", - "#20a000", - "#20a080", - "#a02000", - "#a02080", - "#a0a000", - "#a0a080", - "#2020c0", - "#20a040", - "#20a0c0", - "#a02040", - "#a020c0", - "#a0a040", - "#a0a0c0", - "#206000", - "#206080", - "#20e000", - "#20e080", - "#a06000", - "#a06080", - "#a0e000", - "#a0e080", - "#206040", - "#2060c0", - "#20e040", - "#20e0c0", - "#a06040", - "#a060c0", - "#a0e040", - "#a0e0c0", - "#602080", - "#60a000", - "#60a080", - "#e02000", - "#e02080", - "#e0a000", - "#e0a080", - "#6020c0", - "#60a040", - "#60a0c0", - "#e02040", - "#e020c0", - "#e0a040", - "#e0a0c0", - "#606000", - "#606080", - "#60e000", - "#60e080", - "#e06000", - "#e06080", - "#e0e000", - "#e0e080", - "#606040", - "#6060c0", - "#60e040", - "#60e0c0", - "#e06040", - "#e060c0", - "#e0e040", - "#e0e0c0", - "#20a020", - "#20a0a0", - "#a02020", - "#a020a0", - "#a0a020", - "#a0a0a0", - "#2020e0", - "#20a060", - "#20a0e0", - "#a02060", - "#a020e0", - "#a0a060", - "#a0a0e0", - "#206020", - "#2060a0", - "#20e020", - "#20e0a0", - "#a06020", - "#a060a0", - "#a0e020", - "#a0e0a0", - "#206060", - "#2060e0", - "#20e060", - "#20e0e0", - "#a06060", - "#a060e0", - "#a0e060", - "#a0e0e0", - "#6020a0", - "#60a020", - "#60a0a0", - "#e02020", - "#e020a0", - "#e0a020", - "#e0a0a0", - "#602060", - "#6020e0", - "#60a060", - "#60a0e0", - "#e02060", - "#e020e0", - "#e0a060", - "#e0a0e0", - "#606020", - "#6060a0", - "#60e020", - "#60e0a0", - "#e06020", - "#e060a0", - "#e0e020", - "#e0e0a0", - "#606060", - "#6060e0", - "#60e060", - "#60e0e0", - "#e06060", - "#e060e0", - "#e0e060", - "#008010", - "#008090", - "#800010", - "#800090", - "#808010", - "#808090", - "#0000d0", - "#008050", - "#0080d0", - "#800050", - "#8000d0", - "#808050", - "#8080d0", - "#004010", - "#004090", - "#00c010", - "#00c090", - "#804010", - "#804090", - "#80c010", - "#80c090", - "#004050", - "#0040d0", - "#00c050", - "#00c0d0", - "#804050", - "#8040d0", - "#80c050", - "#80c0d0", - "#400090", - "#408010", - "#408090", - "#c00010", - "#c00090", - "#c08010", - "#c08090", - "#4000d0", - "#408050", - "#4080d0", - "#c00050", - "#c000d0", - "#c08050", - "#c080d0", - "#404010", - "#404090", - "#40c010", - "#40c090", - "#c04010", - "#c04090", - "#c0c010", - "#c0c090", - "#404050", - "#4040d0", - "#40c050", - "#40c0d0", - "#c04050", - "#c040d0", - "#c0c050", - "#0000b0", - "#008030", - "#0080b0", - "#800030", - "#8000b0", - "#808030", - "#8080b0", - "#0000f0", - "#008070", - "#0080f0", - "#800070", - "#8000f0", - "#808070", - "#8080f0", - "#004030", - "#0040b0", - "#00c030", - "#00c0b0", - "#804030", - "#8040b0", - "#80c030", - "#80c0b0", - "#004070", - "#0040f0", - "#00c070", - "#00c0f0", - "#804070", - "#8040f0", - "#80c070", - "#80c0f0", - "#4000b0", - "#408030", - "#4080b0", - "#c00030", - "#c000b0", - "#c08030", - "#c080b0", - "#400070", - "#4000f0", - "#408070", - "#4080f0", - "#c00070", - "#c000f0", - "#c08070", - "#c080f0", - "#404030", - "#4040b0", - "#40c030", - "#40c0b0", - "#c04030", - "#c040b0", - "#c0c030", - "#c0c0b0", - "#404070", - "#4040f0", - "#40c070", - "#40c0f0", - "#c04070", - "#c040f0", - "#c0c070", - "#c0c0f0", - "#002090", - "#00a010", - "#00a090", - "#802010", - "#802090", - "#80a010", - "#80a090", - "#0020d0", - "#00a050", - "#00a0d0", - "#802050", - "#8020d0", - "#80a050", - "#80a0d0", - "#006010", - "#006090", - "#00e010", - "#00e090", - "#806010", - "#806090", - "#80e010", - "#80e090", - "#006050", - "#0060d0", - "#00e050", - "#00e0d0", - "#806050", - "#8060d0", - "#80e050", - "#80e0d0", - "#402090", - "#40a010", - "#40a090", - "#c02010", - "#c02090", - "#c0a010", - "#c0a090", - "#402050", - "#4020d0", - "#40a050", - "#40a0d0", - "#c02050", - "#c020d0", - "#c0a050", - "#c0a0d0", - "#406010", - "#406090", - "#40e010", - "#40e090", - "#c06010", - "#c06090", - "#c0e010", - "#c0e090", - "#406050", - "#4060d0", - "#40e050", - "#40e0d0", - "#c06050", - "#c060d0", - "#c0e050", - "#c0e0d0", - "#0020b0", - "#00a030", - "#00a0b0", - "#802030", - "#8020b0", - "#80a030", - "#80a0b0", - "#0020f0", - "#00a070", - "#00a0f0", - "#802070", - "#8020f0", - "#80a070", - "#80a0f0", - "#006030", - "#0060b0", - "#00e030", - "#00e0b0", - "#806030", - "#8060b0", - "#80e030", - "#80e0b0", - "#006070", - "#0060f0", - "#00e070", - "#00e0f0", - "#806070", - "#8060f0", - "#80e070", - "#80e0f0", - "#4020b0", - "#40a030", - "#40a0b0", - "#c02030", - "#c020b0", - "#c0a030", - "#c0a0b0", - "#4020f0", - "#40a070", - "#40a0f0", - "#c02070", - "#c020f0", - "#c0a070", - "#c0a0f0", - "#406030", - "#4060b0", - "#40e030", - "#40e0b0", - "#c06030", - "#c060b0", - "#c0e030", - "#c0e0b0", - "#406070", - "#4060f0", - "#40e070", - "#40e0f0", - "#c06070", - "#c060f0", - "#c0e070", - "#208010", - "#208090", - "#a00010", - "#a00090", - "#a08010", - "#a08090", - "#2000d0", - "#208050", - "#2080d0", - "#a00050", - "#a000d0", - "#a08050", - "#a080d0", - "#204010", - "#204090", - "#20c010", - "#20c090", - "#a04010", - "#a04090", - "#a0c010", - "#a0c090", - "#204050", - "#2040d0", - "#20c050", - "#20c0d0", - "#a04050", - "#a040d0", - "#a0c050", - "#a0c0d0", - "#600090", - "#608010", - "#608090", - "#e00010", - "#e00090", - "#e08010", - "#e08090", - "#600050", - "#6000d0", - "#608050", - "#6080d0", - "#e00050", - "#e000d0", - "#e08050", - "#e080d0", - "#604010", - "#604090", - "#60c010", - "#60c090", - "#e04010", - "#e04090", - "#e0c010", - "#e0c090", - "#604050", - "#6040d0", - "#60c050", - "#60c0d0", - "#e04050", - "#e040d0", - "#e0c050", - "#e0c0d0", - "#2000b0", - "#208030", - "#2080b0", - "#a00030", - "#a000b0", - "#a08030", - "#a080b0", - "#2000f0", - "#208070", - "#2080f0", - "#a00070", - "#a000f0", - "#a08070", - "#a080f0", - "#204030", - "#2040b0", - "#20c030", - "#20c0b0", - "#a04030", - "#a040b0", - "#a0c030", - "#a0c0b0", - "#204070", - "#2040f0", - "#20c070", - "#20c0f0", - "#a04070", - "#a040f0", - "#a0c070", - "#a0c0f0", - "#6000b0", - "#608030", - "#6080b0", - "#e00030", - "#e000b0", - "#e08030", - "#e080b0", - "#600070", - "#6000f0", - "#608070", - "#e00070", - "#e000f0", - "#e08070", - "#e080f0", - "#604030", - "#6040b0", - "#60c030", - "#60c0b0", - "#e04030", - "#e040b0", - "#e0c030", - "#e0c0b0", - "#604070", - "#6040f0", - "#60c070", - "#60c0f0", - "#e04070", - "#e040f0", - "#e0c070", - "#e0c0f0", - "#20a010", - "#20a090", - "#a02010", - "#a02090", - "#a0a010", - "#a0a090", - "#2020d0", - "#20a050", - "#20a0d0", - "#a02050", - "#a020d0", - "#a0a050", - "#a0a0d0", - "#206010", - "#206090", - "#20e010", - "#20e090", - "#a06010", - "#a06090", - "#a0e010", - "#a0e090", - "#206050", - "#2060d0", - "#20e050", - "#20e0d0", - "#a06050", - "#a060d0", - "#a0e050", - "#a0e0d0", - "#602090", - "#60a010", - "#60a090", - "#e02010", - "#e02090", - "#e0a010", - "#e0a090", - "#602050", - "#6020d0", - "#60a050", - "#60a0d0", - "#e02050", - "#e020d0", - "#e0a050", - "#e0a0d0", - "#606010", - "#606090", - "#60e010", - "#60e090", - "#e06010", - "#e06090", - "#e0e010", - "#e0e090", - "#606050", - "#6060d0", - "#60e050", - "#60e0d0", - "#e06050", - "#e060d0", - "#e0e050", - "#2020b0", - "#20a030", - "#20a0b0", - "#a02030", - "#a020b0", - "#a0a030", - "#a0a0b0", - "#2020f0", - "#20a070", - "#20a0f0", - "#a02070", - "#a020f0", - "#a0a070", - "#a0a0f0", - "#206030", - "#2060b0", - "#20e030", - "#20e0b0", - "#a06030", - "#a060b0", - "#a0e030", - "#a0e0b0", - "#206070", - "#2060f0", - "#20e070", - "#20e0f0", - "#a06070", - "#a060f0", - "#a0e070", - "#a0e0f0", - "#6020b0", - "#60a030", - "#60a0b0", - "#e02030", - "#e020b0", - "#e0a030", - "#e0a0b0", - "#6020f0", - "#60a070", - "#60a0f0", - "#e02070", - "#e020f0", - "#e0a070", - "#e0a0f0", - "#606030", - "#6060b0", - "#60e030", - "#60e0b0", - "#e06030", - "#e060b0", - "#e0e030", - "#e0e0b0", - "#606070", - "#6060f0", - "#60e070", - "#60e0f0", - "#e06070", - "#e060f0", - "#e0e070", -]; - const Graph: FC = ({ expr, endTime, range, resolution, + showExemplars, displayMode, retriggerIdx, + onSelectRange, }) => { - const { ref, width, height } = useElementSize(); + const { ref, width } = useElementSize(); + const [rerender, setRerender] = useState(true); + + const effectiveEndTime = (endTime !== null ? endTime : Date.now()) / 1000; + const startTime = effectiveEndTime - range / 1000; + const effectiveResolution = + resolution || Math.max(Math.floor(range / 250000), 1); - const realEndTime = (endTime !== null ? endTime : Date.now()) / 1000; const { data, error, isFetching, isLoading, refetch } = useAPIQuery({ key: useId(), path: "/query_range", params: { query: expr, - step: ( - resolution || Math.max(Math.floor(range / 250000), 1) - ).toString(), - start: (realEndTime - range / 1000).toString(), - end: realEndTime.toString(), + step: effectiveResolution.toString(), + start: startTime.toString(), + end: effectiveEndTime.toString(), }, enabled: expr !== "", }); + // Keep the displayed chart range separate from the actual query range, so that + // the chart will keep displaying the old range while a new query for a different range + // is still in progress. + const [displayedChartRange, setDisplayedChartRange] = + useState({ + startTime: startTime, + endTime: effectiveEndTime, + resolution: effectiveResolution, + }); + + useEffect(() => { + setDisplayedChartRange({ + startTime: startTime, + endTime: effectiveEndTime, + resolution: effectiveResolution, + }); + }, [data]); + useEffect(() => { expr !== "" && refetch(); }, [retriggerIdx, refetch, expr, endTime, range, resolution]); + useEffect(() => { + if (data !== undefined && rerender) { + setRerender(false); + } + }, [data, rerender, setRerender]); + // TODO: Share all the loading/error/empty data notices with the DataTable. // Show a skeleton only on the first load, not on subsequent ones. @@ -1039,188 +140,26 @@ const Graph: FC = ({ ); } - // const option: EChartsOption = { - // animation: false, - // grid: { - // left: 20, - // top: 20, - // right: 20, - // bottom: 20 + result.length * 24, - // containLabel: true, - // }, - // legend: { - // type: "scroll", - // icon: "square", - // orient: "vertical", - // top: chartHeight + legendMargin, - // bottom: 20, - // left: 30, - // right: 20, - // }, - // xAxis: { - // type: "category", - // // min: realEndTime * 1000 - range, - // // max: realEndTime * 1000, - // data: result[0].values?.map((v) => Math.round(v[0] * 1000)), - // axisLine: { - // show: true, - // }, - // }, - // yAxis: { - // type: "value", - // axisLabel: { - // formatter: formatValue, - // }, - // axisLine: { - // // symbol: "arrow", - // show: true, - // // lineStyle: { - // // type: "dashed", - // // color: "rgba(0, 0, 0, 0.5)", - // // }, - // }, - // }, - // tooltip: { - // show: true, - // trigger: "item", - // transitionDuration: 0, - // axisPointer: { - // type: "cross", - // // snap: true, - // }, - // }, - // series: result.map((series) => ({ - // name: formatSeries(series.metric), - // // data: series.values?.map((v) => [v[0] * 1000, parseFloat(v[1])]), - // data: series.values?.map((v) => parseFloat(v[1])), - // type: "line", - // stack: displayMode === "stacked" ? "total" : undefined, - // // showSymbol: false, - // // fill: displayMode === "stacked" ? "tozeroy" : undefined, - // })), - // }; - - function autoPadRight(self, side, sidesWithAxes, cycleNum) { - const xAxis = self.axes[0]; - - const xVals = xAxis._values; - - if (xVals != null) { - // bail out, force convergence - if (cycleNum > 2) return self._padding[1]; - - const xSplits = xAxis._splits; - const rightSplit = xSplits[xSplits.length - 1]; - const rightSplitCoord = self.valToPos(rightSplit, "x"); - const leftPlotEdge = self.bbox.left / devicePixelRatio; - const rightPlotEdge = leftPlotEdge + self.bbox.width / devicePixelRatio; - const rightChartEdge = rightPlotEdge + self._padding[1]; - - const pxPerChar = 8; - const rightVal = xVals[xVals.length - 1] + ""; - const valHalfWidth = pxPerChar * (rightVal.length / 2); - - const rightValEdge = leftPlotEdge + rightSplitCoord + valHalfWidth; - - if (rightValEdge >= rightChartEdge) { - return rightValEdge - rightPlotEdge; - } - } - - // default size - return 8; - } - - const options: uPlot.Options = { - id: "chart", - width: width - 30, - height: 500, - padding: [null, autoPadRight, null, null], - // plugins: [tooltipPlugin()], - scales: { - x: { - time: false, - }, - }, - legend: { - show: true, - live: false, - markers: { - fill: ( - self: uPlot, - seriesIdx: number - ): CSSStyleDeclaration["borderColor"] => { - return colorPool[seriesIdx % colorPool.length]; - }, - }, - }, - axes: [ - { - labelSize: 20, - stroke: "#333", - values(self, splits) { - return splits.map((s) => s); - }, - }, - { - labelGap: 8, - labelSize: 8 + 12 + 8, - stroke: "#333", - size(self, values, axisIdx, cycleNum) { - const axis = self.axes[axisIdx]; - - // bail out, force convergence - if (cycleNum > 1) { - return axis._size; - } - - let axisSize = axis.ticks.size + axis.gap; - - // find longest value - const longestVal = (values ?? []).reduce( - (acc, val) => (val.length > acc.length ? val : acc), - "" - ); - - if (longestVal != "") { - self.ctx.font = axis.font[0]; - axisSize += - self.ctx.measureText(longestVal).width / devicePixelRatio; - } - - return Math.ceil(axisSize); - }, - }, - ], - series: [ - ...result.map((r, idx) => ({ - label: formatSeries(r.metric), - width: 2, - stroke: colorPool[idx % colorPool.length], - })), - ], - }; - - const seriesData: uPlot.AlignedData = [ - result[0].values?.map((v) => v[0]), - ...result.map((r) => r.values?.map((v) => parseFloat(v[1]))), - ]; - return ( , - }} - styles={{ loader: { width: "100%", height: "100%" } }} + h={570} + overlayProps={{ radius: "sm", blur: 0.5 }} + loaderProps={{ type: "dots", color: "gray" }} + // loaderProps={{ + // children: , + // }} + // styles={{ loader: { width: "100%", height: "100%" } }} /> - ); diff --git a/web/ui/mantine-ui/src/pages/query/QueryPanel.tsx b/web/ui/mantine-ui/src/pages/query/QueryPanel.tsx index 439c1f29e..ab5303dd5 100644 --- a/web/ui/mantine-ui/src/pages/query/QueryPanel.tsx +++ b/web/ui/mantine-ui/src/pages/query/QueryPanel.tsx @@ -7,6 +7,7 @@ import { Input, SegmentedControl, Stack, + Select, } from "@mantine/core"; import { IconChartAreaFilled, @@ -122,7 +123,53 @@ const QueryPanel: FC = ({ idx, metricNames }) => { } /> - +