vmui: change warning display for text fields (#4848) (#4863)

https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4848
This commit is contained in:
Yury Molodov 2023-08-21 15:42:55 +02:00 committed by GitHub
parent 8287749c05
commit ca44b8da1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 112 deletions

View file

@ -5,8 +5,6 @@ import TextField from "../../Main/TextField/TextField";
import Autocomplete from "../../Main/Autocomplete/Autocomplete";
import "./style.scss";
import { QueryStats } from "../../../api/types";
import Tooltip from "../../Main/Tooltip/Tooltip";
import { WarningIcon } from "../../Main/Icons";
import { partialWarning, seriesFetchedWarning } from "./warningText";
export interface QueryEditorProps {
@ -41,7 +39,7 @@ const QueryEditor: FC<QueryEditorProps> = ({
const [openAutocomplete, setOpenAutocomplete] = useState(false);
const autocompleteAnchorEl = useRef<HTMLDivElement>(null);
const warnings = [
const warning = [
{
show: stats?.seriesFetched === "0" && !stats.resultLength,
text: seriesFetchedWarning
@ -50,7 +48,7 @@ const QueryEditor: FC<QueryEditorProps> = ({
show: stats?.isPartial,
text: partialWarning
}
].filter((warning) => warning.show);
].filter((w) => w.show).map(w => w.text).join("");
const handleSelect = (val: string) => {
onChange(val);
@ -104,6 +102,7 @@ const QueryEditor: FC<QueryEditorProps> = ({
type={"textarea"}
autofocus={!!value}
error={error}
warning={warning}
onKeyDown={handleKeyDown}
onChange={onChange}
disabled={disabled}
@ -119,20 +118,6 @@ const QueryEditor: FC<QueryEditorProps> = ({
onFoundOptions={handleChangeFoundOptions}
/>
)}
{!!warnings.length && (
<div className="vm-query-editor-warning">
<Tooltip
placement="bottom-right"
title={(
<div className="vm-query-editor-warning__tooltip">
{warnings.map((warning, index) => <p key={index}>{warning.text}</p>)}
</div>
)}
>
<WarningIcon/>
</Tooltip>
</div>
)}
</div>;
};

View file

@ -7,29 +7,4 @@
max-height: 300px;
overflow: auto;
}
&-warning {
position: absolute;
top: 50%;
right: $padding-global;
transform: translateY(-50%);
display: grid;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
color: $color-warning;
&__tooltip {
white-space: pre-line;
p {
margin-bottom: $padding-small;
&:last-child {
margin-bottom: 0;
}
}
}
}
}

View file

@ -3,7 +3,7 @@ import classNames from "classnames";
import { useMemo } from "preact/compat";
import { useAppState } from "../../../state/common/StateContext";
import useDeviceDetect from "../../../hooks/useDeviceDetect";
import TextFieldError from "./TextFieldError";
import TextFieldMessage from "./TextFieldMessage";
import "./style.scss";
interface TextFieldProps {
@ -11,6 +11,7 @@ interface TextFieldProps {
value?: string | number
type?: HTMLInputTypeAttribute | "textarea"
error?: string
warning?: string
placeholder?: string
endIcon?: ReactNode
startIcon?: ReactNode
@ -30,12 +31,13 @@ const TextField: FC<TextFieldProps> = ({
value,
type = "text",
error = "",
warning = "",
helperText = "",
placeholder,
endIcon,
startIcon,
disabled = false,
autofocus = false,
helperText,
inputmode = "text",
onChange,
onEnter,
@ -53,6 +55,7 @@ const TextField: FC<TextFieldProps> = ({
const inputClasses = classNames({
"vm-text-field__input": true,
"vm-text-field__input_error": error,
"vm-text-field__input_warning": !error && warning,
"vm-text-field__input_icon-start": startIcon,
"vm-text-field__input_disabled": disabled,
"vm-text-field__input_textarea": type === "textarea",
@ -133,12 +136,11 @@ const TextField: FC<TextFieldProps> = ({
)
}
{label && <span className="vm-text-field__label">{label}</span>}
<TextFieldError error={error}/>
{helperText && !error && (
<span className="vm-text-field__helper-text">
{helperText}
</span>
)}
<TextFieldMessage
error={error}
warning={warning}
info={helperText}
/>
</label>
;
};

View file

@ -1,56 +0,0 @@
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;

View file

@ -0,0 +1,72 @@
import React, { FC, useEffect, useRef, useState } from "react";
import useEventListener from "../../../hooks/useEventListener";
import classNames from "classnames";
import "./style.scss";
import { useMemo } from "preact/compat";
interface TextFieldErrorProps {
error: string;
warning: string;
info: string;
}
const TextFieldMessage: FC<TextFieldErrorProps> = ({ error, warning, info }) => {
console.log(warning);
const messageRef = useRef<HTMLSpanElement>(null);
const [isMessageTruncated, setIsMessageTruncated] = useState(false);
const [showFull, setShowFull] = useState(false);
const prefix = useMemo(() => {
if (error) return "ERROR: ";
if (warning) return "WARNING: ";
return "";
}, [error, warning]);
const message = `${prefix}${error || warning || info}`;
const checkIfTextTruncated = () => {
const el = messageRef.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;
setIsMessageTruncated(overflowed);
} else {
setIsMessageTruncated(false);
}
};
const handleClickError = () => {
if (!isMessageTruncated) return;
setShowFull(true);
setIsMessageTruncated(false);
};
useEffect(() => {
setShowFull(false);
checkIfTextTruncated();
}, [messageRef, message]);
useEventListener("resize", checkIfTextTruncated);
if (!error && !warning && !info) return null;
return (
<span
className={classNames({
"vm-text-field__error": true,
"vm-text-field__warning": warning && !error,
"vm-text-field__helper-text": !warning && !error,
"vm-text-field__error_overflowed": isMessageTruncated,
"vm-text-field__error_full": showFull,
})}
data-show={!!message}
ref={messageRef}
onClick={handleClickError}
>
{message}
</span>
);
};
export default TextFieldMessage;

View file

@ -26,6 +26,7 @@
&__label,
&__error,
&__warning,
&__helper-text, {
position: absolute;
left: calc($padding-global/2);
@ -50,12 +51,13 @@
color: $color-text-secondary;
}
&__helper-text,
&__warning,
&__error {
position: relative;
top: calc($font-size-small/-2);
width: fit-content;
overflow-wrap: anywhere;
color: $color-error;
pointer-events: auto;
user-select: text;
@ -69,8 +71,15 @@
}
}
&__error {
color: $color-error;
}
&__warning {
color: $color-warning;
}
&__helper-text {
bottom: calc($font-size-small/-2);
color: $color-text-secondary;
}
@ -93,14 +102,26 @@
}
&_error {
border: 1px solid $color-error;
border-color: $color-error;
&:hover {
border: 1px solid $color-error;
border-color: $color-error;
}
&:focus {
border: 1px solid $color-error;
border-color: $color-error;
}
}
&_warning {
border-color: $color-warning;
&:hover {
border-color: $color-warning;
}
&:focus {
border-color: $color-warning;
}
}

View file

@ -26,6 +26,7 @@ The following `tip` changes can be tested by building VictoriaMetrics components
* FEATURE: [vmbackup](https://docs.victoriametrics.com/vmbackup.html): add support for server-side copy of existing backups. See [these docs](https://docs.victoriametrics.com/vmbackup.html#server-side-copy-of-the-existing-backup) for details.
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): properly handle `unexpected EOF` error when parsing metrics in Prometheus exposition format. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4817).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): make the warning message more noticeable for text fields. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4848).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add button for auto-formatting PromQL/MetricsQL queries. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4681). Thanks to @aramattamara for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/4694).
* BUGFIX: do not allow starting VictoriaMetrics components with improperly set boolean command-line flags in the form `-boolFlagName value`, since this leads to silent incomplete flags' parsing. This form should be replaced with `-boolFlagName=value`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4845).