mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
vmui: allow displaying the full error message on click (#4760)
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4719
This commit is contained in:
parent
336744a93e
commit
cf0077b552
7 changed files with 86 additions and 26 deletions
|
@ -36,7 +36,7 @@ const DateTimeInput: FC<DateTimeInputProps> = ({
|
||||||
const [maskedValue, setMaskedValue] = useState(formatStringDate(value));
|
const [maskedValue, setMaskedValue] = useState(formatStringDate(value));
|
||||||
const [focusToTime, setFocusToTime] = useState(false);
|
const [focusToTime, setFocusToTime] = useState(false);
|
||||||
const [awaitChangeForEnter, setAwaitChangeForEnter] = useState(false);
|
const [awaitChangeForEnter, setAwaitChangeForEnter] = useState(false);
|
||||||
const error = dayjs(maskedValue).isValid() ? "" : "Expected format: YYYY-MM-DD HH:mm:ss";
|
const error = dayjs(maskedValue).isValid() ? "" : "Invalid date format";
|
||||||
|
|
||||||
const handleMaskedChange = (e: ChangeEvent<HTMLInputElement>) => {
|
const handleMaskedChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setMaskedValue(e.currentTarget.value);
|
setMaskedValue(e.currentTarget.value);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import classNames from "classnames";
|
||||||
import { useMemo } from "preact/compat";
|
import { useMemo } from "preact/compat";
|
||||||
import { useAppState } from "../../../state/common/StateContext";
|
import { useAppState } from "../../../state/common/StateContext";
|
||||||
import useDeviceDetect from "../../../hooks/useDeviceDetect";
|
import useDeviceDetect from "../../../hooks/useDeviceDetect";
|
||||||
|
import TextFieldError from "./TextFieldError";
|
||||||
import "./style.scss";
|
import "./style.scss";
|
||||||
|
|
||||||
interface TextFieldProps {
|
interface TextFieldProps {
|
||||||
|
@ -132,12 +133,7 @@ const TextField: FC<TextFieldProps> = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{label && <span className="vm-text-field__label">{label}</span>}
|
{label && <span className="vm-text-field__label">{label}</span>}
|
||||||
<span
|
<TextFieldError error={error}/>
|
||||||
className="vm-text-field__error"
|
|
||||||
data-show={!!error}
|
|
||||||
>
|
|
||||||
{error}
|
|
||||||
</span>
|
|
||||||
{helperText && !error && (
|
{helperText && !error && (
|
||||||
<span className="vm-text-field__helper-text">
|
<span className="vm-text-field__helper-text">
|
||||||
{helperText}
|
{helperText}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import React, { FC, useEffect, useRef, useState } from "react";
|
||||||
|
import useEventListener from "../../../hooks/useEventListener";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import "./style.scss";
|
||||||
|
|
||||||
|
interface TextFieldErrorProps {
|
||||||
|
error: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TextFieldError: FC<TextFieldErrorProps> = ({ error }) => {
|
||||||
|
const errorRef = useRef<HTMLSpanElement>(null);
|
||||||
|
const [isErrorTruncated, setIsErrorTruncated] = useState(false);
|
||||||
|
const [showFull, setShowFull] = useState(false);
|
||||||
|
|
||||||
|
const checkIfTextTruncated = () => {
|
||||||
|
const el = errorRef.current;
|
||||||
|
if (el) {
|
||||||
|
const { offsetWidth, scrollWidth, offsetHeight, scrollHeight } = el;
|
||||||
|
// The "+1" is for the scrollbar in Firefox
|
||||||
|
const overflowed = (offsetWidth + 1) < scrollWidth || (offsetHeight + 1) < scrollHeight;
|
||||||
|
setIsErrorTruncated(overflowed);
|
||||||
|
} else {
|
||||||
|
setIsErrorTruncated(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClickError = () => {
|
||||||
|
if (!isErrorTruncated) return;
|
||||||
|
setShowFull(true);
|
||||||
|
setIsErrorTruncated(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setShowFull(false);
|
||||||
|
checkIfTextTruncated();
|
||||||
|
}, [errorRef, error]);
|
||||||
|
|
||||||
|
useEventListener("resize", checkIfTextTruncated);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={classNames({
|
||||||
|
"vm-text-field__error": true,
|
||||||
|
"vm-text-field__error_overflowed": isErrorTruncated,
|
||||||
|
"vm-text-field__error_full": showFull,
|
||||||
|
})}
|
||||||
|
data-show={!!error}
|
||||||
|
ref={errorRef}
|
||||||
|
onClick={handleClickError}
|
||||||
|
>
|
||||||
|
{error}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TextFieldError;
|
|
@ -40,14 +40,9 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 2; /* number of lines to show */
|
|
||||||
line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
-webkit-line-clamp: 1; /* number of lines to show */
|
-webkit-line-clamp: 1; /* number of lines to show */
|
||||||
line-clamp: 1;
|
line-clamp: 1;
|
||||||
}
|
-webkit-box-orient: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__label {
|
&__label {
|
||||||
|
@ -56,10 +51,22 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&__error {
|
&__error {
|
||||||
top: calc((100% - ($font-size-small/2)) - 2px);
|
position: relative;
|
||||||
|
top: calc($font-size-small/-2);
|
||||||
|
width: fit-content;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
color: $color-error;
|
color: $color-error;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
|
|
||||||
|
&_full {
|
||||||
|
display: block;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_overflowed {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__helper-text {
|
&__helper-text {
|
||||||
|
@ -117,9 +124,9 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
max-width: 15px;
|
max-width: 15px;
|
||||||
top: auto;
|
top: 0;
|
||||||
left: $padding-small;
|
left: $padding-small;
|
||||||
height: 100%;
|
height: 40px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
color: $color-text-secondary;
|
color: $color-text-secondary;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ const Tooltip: FC<TooltipProps> = ({
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("scroll", onScrollWindow);
|
window.removeEventListener("scroll", onScrollWindow);
|
||||||
};
|
};
|
||||||
}, [isOpen]);
|
}, [isOpen, title]);
|
||||||
|
|
||||||
const popperStyle = useMemo(() => {
|
const popperStyle = useMemo(() => {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
|
|
@ -52,6 +52,7 @@ input[type=number]::-webkit-outer-spin-button {
|
||||||
left: $padding-global;
|
left: $padding-global;
|
||||||
bottom: $padding-global;
|
bottom: $padding-global;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
|
animation: vm-slide-snackbar 150ms cubic-bezier(0.280, 0.840, 0.420, 1.1);
|
||||||
|
|
||||||
&-content {
|
&-content {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -71,7 +72,7 @@ input[type=number]::-webkit-outer-spin-button {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
animation: vm-slide-snackbar 150ms cubic-bezier(0.280, 0.840, 0.420, 1.1);
|
}
|
||||||
|
|
||||||
@keyframes vm-slide-snackbar {
|
@keyframes vm-slide-snackbar {
|
||||||
0% {
|
0% {
|
||||||
|
@ -81,7 +82,6 @@ input[type=number]::-webkit-outer-spin-button {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
|
|
|
@ -34,6 +34,7 @@ The following `tip` changes can be tested by building VictoriaMetrics components
|
||||||
* FEATURE: [vmctl](https://docs.victoriametrics.com/vmctl.html): add support of `week` step for [time-based chunking migration](https://docs.victoriametrics.com/vmctl.html#using-time-based-chunking-of-migration). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4738).
|
* FEATURE: [vmctl](https://docs.victoriametrics.com/vmctl.html): add support of `week` step for [time-based chunking migration](https://docs.victoriametrics.com/vmctl.html#using-time-based-chunking-of-migration). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4738).
|
||||||
* FEATURE: [vmctl](https://docs.victoriametrics.com/vmctl.html): do not add `/api/v1/read` suffix to remote read storage address defined by `--remote-read-src-addr` if a `--remote-read-disable-path-append` command-line flag is set. It allows an overriding path for remote-read API via `--remote-read-src-addr`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4655).
|
* FEATURE: [vmctl](https://docs.victoriametrics.com/vmctl.html): do not add `/api/v1/read` suffix to remote read storage address defined by `--remote-read-src-addr` if a `--remote-read-disable-path-append` command-line flag is set. It allows an overriding path for remote-read API via `--remote-read-src-addr`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4655).
|
||||||
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add warning in query field of vmui for partial data responses. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4721).
|
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add warning in query field of vmui for partial data responses. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4721).
|
||||||
|
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): allow displaying the full error message on click for trimmed error messages in vmui. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4719).
|
||||||
* FEATURE: [Official Grafana dashboards for VictoriaMetrics](https://grafana.com/orgs/victoriametrics): add `Concurrent inserts` panel to vmagent's dasbhoard. The new panel supposed to show whether the number of concurrent inserts processed by vmagent isn't reaching the limit.
|
* FEATURE: [Official Grafana dashboards for VictoriaMetrics](https://grafana.com/orgs/victoriametrics): add `Concurrent inserts` panel to vmagent's dasbhoard. The new panel supposed to show whether the number of concurrent inserts processed by vmagent isn't reaching the limit.
|
||||||
* FEATURE: [Official Grafana dashboards for VictoriaMetrics](https://grafana.com/orgs/victoriametrics): add panels for absolute Mem and CPU usage by vmalert. See related issue [here](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4627).
|
* FEATURE: [Official Grafana dashboards for VictoriaMetrics](https://grafana.com/orgs/victoriametrics): add panels for absolute Mem and CPU usage by vmalert. See related issue [here](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4627).
|
||||||
* FEATURE: [Official Grafana dashboards for VictoriaMetrics](https://grafana.com/orgs/victoriametrics): correctly calculate `Bytes per point` value for single-server and cluster VM dashboards. Before, the calculation mistakenly accounted for the number of entries in indexdb in denominator, which could have shown lower values than expected.
|
* FEATURE: [Official Grafana dashboards for VictoriaMetrics](https://grafana.com/orgs/victoriametrics): correctly calculate `Bytes per point` value for single-server and cluster VM dashboards. Before, the calculation mistakenly accounted for the number of entries in indexdb in denominator, which could have shown lower values than expected.
|
||||||
|
|
Loading…
Reference in a new issue