Only copy matchers on double click and add error handling (#16165)

The useClipboard hook also just uses navigator.clipboard.writeText() under
the hood, but the timeout and state handling that the hook provides were
just not a good fit for showing a one-shot notification with error
detectionm, so doing the copying manually.

Addresses part of https://github.com/prometheus/prometheus/issues/16162

Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
Julius Volz 2025-03-05 10:18:09 +01:00 committed by GitHub
parent 631890b38e
commit 70aea5dd8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,7 +3,6 @@ import React, { FC } from "react";
import { formatSeries } from "../../lib/formatSeries";
import classes from "./SeriesName.module.css";
import { escapeString } from "../../lib/escapeString";
import { useClipboard } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import {
maybeQuoteLabelName,
@ -15,9 +14,34 @@ interface SeriesNameProps {
format: boolean;
}
const SeriesName: FC<SeriesNameProps> = ({ labels, format }) => {
const clipboard = useClipboard();
const copyMatcher = (matcher: string) => {
if ("clipboard" in navigator) {
navigator.clipboard
.writeText(matcher)
.then(() =>
notifications.show({
title: "Copied matcher!",
message: `Label matcher ${matcher} copied to clipboard`,
})
)
.catch(() =>
notifications.show({
color: "red",
title: "Failed to copy matcher!",
message: "Label matcher could not be copied to clipboard.",
})
);
} else {
notifications.show({
color: "red",
title: "Failed to copy matcher!",
message:
"Clipboard API is not supported in this context (most likely due to non-HTTPS origin).",
});
}
};
const SeriesName: FC<SeriesNameProps> = ({ labels, format }) => {
const renderFormatted = (): React.ReactElement => {
const metricExtendedCharset =
labels && metricContainsExtendedCharset(labels.__name__ || "");
@ -49,15 +73,8 @@ const SeriesName: FC<SeriesNameProps> = ({ labels, format }) => {
{!first && ", "}
<span
className={classes.labelPair}
onClick={(e) => {
const text = e.currentTarget.innerText;
clipboard.copy(text);
notifications.show({
title: "Copied matcher!",
message: `Label matcher ${text} copied to clipboard`,
});
}}
title="Click to copy label matcher"
onDoubleClick={(e) => copyMatcher(e.currentTarget.innerText)}
title="Double click to copy label matcher"
>
<span className={classes.labelName}>
{maybeQuoteLabelName(label)}