diff --git a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditor.tsx b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditor.tsx index 863918c2aa..78e3053f0c 100644 --- a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditor.tsx +++ b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditor.tsx @@ -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 = ({ const [openAutocomplete, setOpenAutocomplete] = useState(false); const autocompleteAnchorEl = useRef(null); - const warnings = [ + const warning = [ { show: stats?.seriesFetched === "0" && !stats.resultLength, text: seriesFetchedWarning @@ -50,7 +48,7 @@ const QueryEditor: FC = ({ 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 = ({ type={"textarea"} autofocus={!!value} error={error} + warning={warning} onKeyDown={handleKeyDown} onChange={onChange} disabled={disabled} @@ -119,20 +118,6 @@ const QueryEditor: FC = ({ onFoundOptions={handleChangeFoundOptions} /> )} - {!!warnings.length && ( -
- - {warnings.map((warning, index) =>

{warning.text}

)} -
- )} - > - - - - )} ; }; diff --git a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/style.scss b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/style.scss index 7c8354845b..6e9d4277f5 100644 --- a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/style.scss +++ b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/style.scss @@ -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; - } - } - } - } } diff --git a/app/vmui/packages/vmui/src/components/Main/TextField/TextField.tsx b/app/vmui/packages/vmui/src/components/Main/TextField/TextField.tsx index 2514bfb9da..7e6211e3bb 100644 --- a/app/vmui/packages/vmui/src/components/Main/TextField/TextField.tsx +++ b/app/vmui/packages/vmui/src/components/Main/TextField/TextField.tsx @@ -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 = ({ 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 = ({ 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 = ({ ) } {label && {label}} - - {helperText && !error && ( - - {helperText} - - )} + ; }; diff --git a/app/vmui/packages/vmui/src/components/Main/TextField/TextFieldError.tsx b/app/vmui/packages/vmui/src/components/Main/TextField/TextFieldError.tsx deleted file mode 100644 index 3d3b1a95ac..0000000000 --- a/app/vmui/packages/vmui/src/components/Main/TextField/TextFieldError.tsx +++ /dev/null @@ -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 = ({ error }) => { - const errorRef = useRef(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 ( - - {error} - - ); -}; - -export default TextFieldError; diff --git a/app/vmui/packages/vmui/src/components/Main/TextField/TextFieldMessage.tsx b/app/vmui/packages/vmui/src/components/Main/TextField/TextFieldMessage.tsx new file mode 100644 index 0000000000..db1c2f1c7f --- /dev/null +++ b/app/vmui/packages/vmui/src/components/Main/TextField/TextFieldMessage.tsx @@ -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 = ({ error, warning, info }) => { + console.log(warning); + const messageRef = useRef(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 ( + + {message} + + ); +}; + +export default TextFieldMessage; diff --git a/app/vmui/packages/vmui/src/components/Main/TextField/style.scss b/app/vmui/packages/vmui/src/components/Main/TextField/style.scss index 44a854bbfe..d94b61e903 100644 --- a/app/vmui/packages/vmui/src/components/Main/TextField/style.scss +++ b/app/vmui/packages/vmui/src/components/Main/TextField/style.scss @@ -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; } } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 69f0506de8..35c5539bcd 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -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).