diff --git a/app/vmui/packages/vmui/eslint.config.js b/app/vmui/packages/vmui/eslint.config.js index f75c63e6fe..4d6f570616 100644 --- a/app/vmui/packages/vmui/eslint.config.js +++ b/app/vmui/packages/vmui/eslint.config.js @@ -82,7 +82,15 @@ export default [...compat.extends( "react/jsx-first-prop-new-line": [1, "multiline"], // Disable core indent rule due to recursion issues in ESLint 9; use JSX-specific rules instead - indent: "off", + indent: ["error", 2, { + SwitchCase: 1, + ignoredNodes: [ + "JSXElement", + "JSXElement *", + "JSXFragment", + "JSXFragment *", + ], + }], "react/jsx-indent": ["error", 2], "react/jsx-indent-props": ["error", 2], diff --git a/app/vmui/packages/vmui/src/api/types.ts b/app/vmui/packages/vmui/src/api/types.ts index 0acb4e92b5..7e8326a58d 100644 --- a/app/vmui/packages/vmui/src/api/types.ts +++ b/app/vmui/packages/vmui/src/api/types.ts @@ -51,7 +51,9 @@ export interface LegendLogHits { export interface LegendLogHitsMenu { title: string; - icon?: ReactNode; + iconStart?: ReactNode; + iconEnd?: ReactNode; + shortcut?: string; handler?: () => void; } diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/BarHitsLegendItem.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/BarHitsLegendItem.tsx index f3fa4a7fc7..d2167f984d 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/BarHitsLegendItem.tsx +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/BarHitsLegendItem.tsx @@ -8,6 +8,8 @@ import Popper from "../../../Main/Popper/Popper"; import useBoolean from "../../../../hooks/useBoolean"; import LegendHitsMenu from "../LegendHitsMenu/LegendHitsMenu"; import { ExtraFilter } from "../../../../pages/OverviewPage/FiltersBar/types"; +import { useCallback } from "react"; +import useLegendHitsVisibilityMenu from "./hooks/useLegendHitsVisibilityMenu"; interface Props { legend: LegendLogHits; @@ -27,6 +29,7 @@ const BarHitsLegendItem: FC = ({ legend, series, onRedrawGraph, onApplyFi const [clickPosition, setClickPosition] = useState<{ top: number; left: number } | null>(null); const targetSeries = useMemo(() => series.find(s => s.label === legend.label), [series]); + const isOnlyTargetVisible = series.every(s => s === targetSeries || !s.show); const fields = useMemo(() => getStreamPairs(legend.label), [legend.label]); @@ -39,6 +42,47 @@ const BarHitsLegendItem: FC = ({ legend, series, onRedrawGraph, onApplyFi handleOpenContextMenu(); }; + const handleVisibilityToggle = useCallback(() => { + if (!targetSeries) return; + targetSeries.show = !targetSeries.show; + onRedrawGraph(); + handleCloseContextMenu(); + }, [targetSeries, onRedrawGraph, handleCloseContextMenu]); + + const handleFocusToggle = useCallback(() => { + series.forEach(s => { + s.show = isOnlyTargetVisible || (s === targetSeries); + }); + onRedrawGraph(); + handleCloseContextMenu(); + }, [series, isOnlyTargetVisible, targetSeries, onRedrawGraph, handleCloseContextMenu]); + + const handleClickByLegend = (e: MouseEvent) => { + const { ctrlKey, metaKey, altKey } = e; + + // alt + key // see useLegendHitsVisibilityMenu.tsx + if (altKey) { + handleVisibilityToggle(); + return; + } + + // cmd/ctrl + click // see useLegendHitsVisibilityMenu.tsx + const ctrlMetaKey = ctrlKey || metaKey; + if (ctrlMetaKey) { + handleFocusToggle(); + return; + } + + handleContextMenu(e); + }; + + const optionsVisibilitySection = useLegendHitsVisibilityMenu({ + targetSeries, + isOnlyTargetVisible, + handleVisibilityToggle, + handleFocusToggle + }); + return (
= ({ legend, series, onRedrawGraph, onApplyFi "vm-bar-hits-legend-item_active": openContextMenu, "vm-bar-hits-legend-item_hide": !targetSeries?.show, })} - onClick={handleContextMenu} + onClick={handleClickByLegend} >
= ({ legend, series, onRedrawGraph, onApplyFi diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/hooks/useLegendHitsVisibilityMenu.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/hooks/useLegendHitsVisibilityMenu.tsx new file mode 100644 index 0000000000..824b080601 --- /dev/null +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/hooks/useLegendHitsVisibilityMenu.tsx @@ -0,0 +1,38 @@ +import { LegendLogHitsMenu } from "../../../../../api/types"; +import { useMemo } from "react"; +import { FocusIcon, UnfocusIcon, VisibilityIcon, VisibilityOffIcon } from "../../../../Main/Icons"; +import { altKeyLabel, ctrlKeyLabel } from "../../../../../utils/keyboard"; +import { Series } from "uplot"; + +type Props = { + targetSeries?: Series; + isOnlyTargetVisible: boolean; + handleVisibilityToggle: () => void; + handleFocusToggle: () => void; +} + +const useLegendHitsVisibilityMenu = ({ + targetSeries, + isOnlyTargetVisible, + handleVisibilityToggle, + handleFocusToggle +}: Props): LegendLogHitsMenu[] => { + const isShow = Boolean(targetSeries?.show); + + return useMemo(() => [ + { + title: isShow ? "Hide this series" : "Show this series", + iconStart: isShow ? : , + shortcut: `${altKeyLabel} + Click`, // handled in BarHitsLegendItem.tsx + handler: handleVisibilityToggle, + }, + { + title: isOnlyTargetVisible ? "Show all series" : "Show only this series", + iconStart: isOnlyTargetVisible ? : , + shortcut: `${ctrlKeyLabel} + Click`, // handled in BarHitsLegendItem.tsx + handler: handleFocusToggle, + }, + ], [isOnlyTargetVisible, isShow, handleVisibilityToggle, handleFocusToggle]); +}; + +export default useLegendHitsVisibilityMenu; diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenu.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenu.tsx index 31deef6f7b..93b1da6232 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenu.tsx +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenu.tsx @@ -1,7 +1,6 @@ import { FC } from "preact/compat"; -import { Series } from "uplot"; import "./style.scss"; -import { LegendLogHits } from "../../../../api/types"; +import { LegendLogHits, LegendLogHitsMenu } from "../../../../api/types"; import LegendHitsMenuStats from "./LegendHitsMenuStats"; import LegendHitsMenuBase from "./LegendHitsMenuBase"; import LegendHitsMenuRow from "./LegendHitsMenuRow"; @@ -10,32 +9,20 @@ import { LOGS_LIMIT_HITS } from "../../../../constants/logs"; import LegendHitsMenuVisibility from "./LegendHitsMenuVisibility"; import { ExtraFilter } from "../../../../pages/OverviewPage/FiltersBar/types"; -const otherDescription = `aggregated results for fields not in the top ${LOGS_LIMIT_HITS}`; +const otherDescription = `Aggregated results for fields not in the top ${LOGS_LIMIT_HITS}`; interface Props { legend: LegendLogHits; fields: string[]; - series: Series[]; + optionsVisibilitySection: LegendLogHitsMenu[]; onApplyFilter: (value: ExtraFilter) => void; - onRedrawGraph: () => void; onClose: () => void; } -const LegendHitsMenu: FC = ({ legend, fields, series, onApplyFilter, onRedrawGraph, onClose }) => { +const LegendHitsMenu: FC = ({ legend, fields, optionsVisibilitySection, onApplyFilter, onClose }) => { return (
- {legend.isOther && ( -
- -
- )} - - + {!legend.isOther && ( = ({ legend, fields, series, onApplyFilter, onRe )} + + {legend.isOther && ( +
+ +
+ )}
); }; diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuBase.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuBase.tsx index 8fba820a51..ecb73da17b 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuBase.tsx +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuBase.tsx @@ -33,29 +33,27 @@ const LegendHitsMenuBase: FC = ({ legend, onApplyFilter, onClose }) => { const options: LegendLogHitsMenu[] = [ { title: `Copy ${groupFieldHits} name`, - icon: , + iconStart: , handler: handlerCopyLabel, }, { title: `Add ${groupFieldHits} to filter`, - icon: , + iconStart: , handler: handleAddStreamToFilter(ExtraFilterOperator.Equals), }, { title: `Exclude ${groupFieldHits} to filter`, - icon: , + iconStart: , handler: handleAddStreamToFilter(ExtraFilterOperator.NotEquals), } ]; return (
- {options.map(({ icon, title, handler }) => ( + {options.map(({ ...menuProps }) => ( ))}
diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuFields.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuFields.tsx index 73588327a0..e216c3118d 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuFields.tsx +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuFields.tsx @@ -47,17 +47,17 @@ const LegendHitsMenuFields: FC = ({ fields, onApplyFilter, onClose }) => return [ { title: "Copy", - icon: , + iconStart: , handler: handleCopy(field), }, { title: "Add to filter", - icon: , + iconStart: , handler: handleAddToFilter(field, ExtraFilterOperator.Equals), }, { title: "Exclude to filter", - icon: , + iconStart: , handler: handleAddToFilter(field, ExtraFilterOperator.NotEquals), } ]; diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuRow.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuRow.tsx index 3151580da1..bc04c7fbd1 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuRow.tsx +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuRow.tsx @@ -7,6 +7,7 @@ import useClickOutside from "../../../../hooks/useClickOutside"; interface Props { title: string; + shortcut?: string; handler?: () => void; iconStart?: ReactNode; iconEnd?: ReactNode; @@ -14,7 +15,7 @@ interface Props { submenu?: LegendLogHitsMenu[]; } -const LegendHitsMenuRow: FC = ({ title, handler, iconStart, iconEnd, className, submenu }) => { +const LegendHitsMenuRow: FC = ({ title, shortcut, handler, iconStart, iconEnd, className, submenu }) => { const containerRef = useRef(null); const titleRef = useRef(null); const submenuRef = useRef(null); @@ -79,6 +80,7 @@ const LegendHitsMenuRow: FC = ({ title, handler, iconStart, iconEnd, clas {iconStart &&
{iconStart}
} {isOverflownTitle ? ({titleContent}) : titleContent} {iconEnd && !hasSubmenu &&
{iconEnd}
} + {shortcut &&
{shortcut}
} {hasSubmenu && (
@@ -96,12 +98,10 @@ const LegendHitsMenuRow: FC = ({ title, handler, iconStart, iconEnd, clas })} >
- {submenu.map(({ icon, title, handler }) => ( + {submenu.map(({ ...menuProps }) => ( ))}
diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuVisibility.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuVisibility.tsx index 31a8721bd5..3ee2bd3d7b 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuVisibility.tsx +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/LegendHitsMenuVisibility.tsx @@ -1,60 +1,18 @@ -import { FC, useCallback } from "preact/compat"; +import { FC } from "preact/compat"; import LegendHitsMenuRow from "./LegendHitsMenuRow"; -import { FocusIcon, UnfocusIcon, VisibilityIcon, VisibilityOffIcon } from "../../../Main/Icons"; -import { LegendLogHits, LegendLogHitsMenu } from "../../../../api/types"; -import { Series } from "uplot"; -import { useMemo } from "react"; +import { LegendLogHitsMenu } from "../../../../api/types"; -interface Props { - legend: LegendLogHits; - series: Series[]; - onRedrawGraph: () => void; - onClose: () => void; +export interface LegendMenuVisibilityProps { + options: LegendLogHitsMenu[] } -const LegendHitsMenuVisibility: FC = ({ legend, series, onRedrawGraph, onClose }) => { - - const targetSeries = useMemo(() => series.find(s => s.label === legend.label), [series]); - - const isShow = Boolean(targetSeries?.show); - const isOnlyTargetVisible = series.every(s => s === targetSeries || !s.show); - - const handleVisibilityToggle = useCallback(() => { - if (!targetSeries) return; - targetSeries.show = !targetSeries.show; - onRedrawGraph(); - onClose(); - }, [targetSeries, onRedrawGraph, onClose]); - - const handleFocusToggle = useCallback(() => { - series.forEach(s => { - s.show = isOnlyTargetVisible || (s === targetSeries); - }); - onRedrawGraph(); - onClose(); - }, [series, isOnlyTargetVisible, targetSeries, onRedrawGraph, onClose]); - - const options: LegendLogHitsMenu[] = useMemo(() => [ - { - title: isShow ? "Hide series" : "Show series", - icon: isShow ? : , - handler: handleVisibilityToggle, - }, - { - title: isOnlyTargetVisible ? "Show all series" : "Focus on series", - icon: isOnlyTargetVisible ? : , - handler: handleFocusToggle, - }, - ], [isOnlyTargetVisible, isShow, handleFocusToggle, handleVisibilityToggle]); - +const LegendHitsMenuVisibility: FC = ({ options }) => { return (
- {options.map(({ icon, title, handler }) => ( + {options.map(({ ...menuProps }) => ( ))}
diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/style.scss b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/style.scss index eaec0d7114..5a0175309c 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/style.scss +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/LegendHitsMenu/style.scss @@ -34,6 +34,7 @@ &_info { font-size: $font-size-small; font-weight: 500; + font-style: italic; } } @@ -78,6 +79,12 @@ overflow: hidden; text-overflow: ellipsis; } + + &__shortcut { + font-size: $font-size-small; + color: $color-text-secondary; + white-space: nowrap; + } } &-other-list { diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/hooks/useBarHitsOptions.ts b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/hooks/useBarHitsOptions.ts index 1a553d0b72..b998901b61 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/hooks/useBarHitsOptions.ts +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/hooks/useBarHitsOptions.ts @@ -37,7 +37,7 @@ interface UseGetBarHitsOptionsArgs { timezone: string; } -export const OTHER_HITS_LABEL = "other"; +export const OTHER_HITS_LABEL = "other fields"; export const getLabelFromLogHit = (logHit: LogHits) => { if (logHit?._isOther) return OTHER_HITS_LABEL; diff --git a/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/ShortcutKeys.tsx b/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/ShortcutKeys.tsx index b57d1c79f1..5241e9bf6d 100644 --- a/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/ShortcutKeys.tsx +++ b/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/ShortcutKeys.tsx @@ -6,10 +6,11 @@ import keyList from "./constants/keyList"; import { isMacOs } from "../../../utils/detect-device"; import useBoolean from "../../../hooks/useBoolean"; import useEventListener from "../../../hooks/useEventListener"; +import { ctrlKeyLabel } from "../../../utils/keyboard"; const title = "Shortcut keys"; const isMac = isMacOs(); -const keyOpenHelp = isMac ? "Cmd + /" : "F1"; +const keyOpenHelp = isMac ? `${ctrlKeyLabel} + /` : "F1"; type Props = { children?: ReactNode diff --git a/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/constants/keyList.tsx b/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/constants/keyList.tsx index 92895988c8..d19cd91687 100644 --- a/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/constants/keyList.tsx +++ b/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/constants/keyList.tsx @@ -1,8 +1,9 @@ import { isMacOs } from "../../../../utils/detect-device"; +import { altKeyLabel, ctrlKeyLabel } from "../../../../utils/keyboard"; -const ctrlMeta = {isMacOs() ? "Cmd" : "Ctrl"}; +const ctrlMeta = {ctrlKeyLabel}; -export const AUTOCOMPLETE_QUICK_KEY = <>{{isMacOs() ? "Option" : "Ctrl"}} + Space; +export const AUTOCOMPLETE_QUICK_KEY = <>{{isMacOs() ? altKeyLabel : "Ctrl"}} + Space; const keyList = [ { @@ -48,6 +49,14 @@ const keyList = [ { keys: <>click on legend item, description: "Open the legend item menu" + }, + { + keys: <>{altKeyLabel} + click on legend item, + description: "Hide or show this series" + }, + { + keys: <>{ctrlMeta} + click on legend item, + description: "Show only this series or show all series" } ] }, diff --git a/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/style.scss b/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/style.scss index 92d778619f..584a1e32cc 100644 --- a/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/style.scss +++ b/app/vmui/packages/vmui/src/components/Main/ShortcutKeys/style.scss @@ -54,6 +54,7 @@ background-repeat: repeat-x; border: $border-divider; border-radius: 4px; + text-transform: capitalize; } svg { diff --git a/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsHelps/OverviewFieldsHelpContent.tsx b/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsHelps/OverviewFieldsHelpContent.tsx index 5ae7b32aa8..75b8e1b2a0 100644 --- a/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsHelps/OverviewFieldsHelpContent.tsx +++ b/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsHelps/OverviewFieldsHelpContent.tsx @@ -1,3 +1,5 @@ +import { ctrlKeyLabel } from "../../../../utils/keyboard"; + const DocFieldNames = () => ( (

Click behavior

  • Click a row → selects the name and focuses it (adds a blue filter badge).
  • -
  • Ctrl/Cmd + Click → applies Exclude immediately.
  • +
  • {ctrlKeyLabel} + Click → applies Exclude immediately.
  • See Row actions for more options.
@@ -68,7 +70,7 @@ const OverviewFieldsHelpContent = () => (

Click behavior

  • Click a row → focuses the value (adds a blue filter badge).
  • -
  • Ctrl/Cmd + Click → applies Exclude immediately.
  • +
  • {ctrlKeyLabel} + Click → applies Exclude immediately.
  • See Row actions.
diff --git a/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopFieldNames.tsx b/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopFieldNames.tsx index e72b073d1d..db80a55a92 100644 --- a/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopFieldNames.tsx +++ b/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopFieldNames.tsx @@ -11,8 +11,8 @@ import { useOverviewState } from "../../../../state/overview/OverviewStateContex import { ExtraFilterOperator } from "../../FiltersBar/types"; import TopRowMenu from "../FieldRowMenu/TopRowMenu"; import { CopyIcon, FilterIcon, FilterOffIcon, FocusIcon, UnfocusIcon } from "../../../../components/Main/Icons"; -import { isMacOs } from "../../../../utils/detect-device"; import useCopyToClipboard from "../../../../hooks/useCopyToClipboard"; +import { altKeyLabel, ctrlKeyLabel } from "../../../../utils/keyboard"; const TopFieldNames: FC = () => { const { period: { start, end } } = useTimeState(); @@ -81,13 +81,13 @@ const TopFieldNames: FC = () => { { label: "Include", icon: , - shortcut: (isMacOs() ? "Option" : "Alt") + " + Click", + shortcut: `${altKeyLabel} + Click`, onClick: () => handleAddIncludeFilter(row) }, { label: "Exclude", icon: , - shortcut: (isMacOs() ? "Cmd" : "Ctrl") + " + Click", + shortcut: `${ctrlKeyLabel} + Click`, onClick: () => handleAddExcludeFilter(row) }, ], diff --git a/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopFieldValues.tsx b/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopFieldValues.tsx index 272e844afb..ba836928eb 100644 --- a/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopFieldValues.tsx +++ b/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopFieldValues.tsx @@ -14,8 +14,8 @@ import { buildFieldValuesQuery } from "./topFieldValuesUtils"; import { useOverviewState } from "../../../../state/overview/OverviewStateContext"; import useCopyToClipboard from "../../../../hooks/useCopyToClipboard"; import { CopyIcon, FilterIcon, FilterOffIcon, FocusIcon, UnfocusIcon } from "../../../../components/Main/Icons"; -import { isMacOs } from "../../../../utils/detect-device"; import TopRowMenu from "../FieldRowMenu/TopRowMenu"; +import { altKeyLabel, ctrlKeyLabel } from "../../../../utils/keyboard"; const MODE_CONFIG = { top: { @@ -115,13 +115,13 @@ const TopFieldValues: FC = ({ scope }) => { { label: "Include", icon: , - shortcut: (isMacOs() ? "Option" : "Alt") + " + Click", + shortcut: `${altKeyLabel} + Click`, onClick: () => handleAddFilter(row, ExtraFilterOperator.Equals) }, { label: "Exclude", icon: , - shortcut: `${isMacOs() ? "Cmd" : "Ctrl"} + Click`, + shortcut: `${ctrlKeyLabel} + Click`, onClick: () => handleAddFilter(row, ExtraFilterOperator.NotEquals) } ], diff --git a/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopStreamNames.tsx b/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopStreamNames.tsx index 98c211f2f8..600a89c54e 100644 --- a/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopStreamNames.tsx +++ b/app/vmui/packages/vmui/src/pages/OverviewPage/OverviewFields/OverviewFieldsTables/TopStreamNames.tsx @@ -11,8 +11,8 @@ import { useOverviewState } from "../../../../state/overview/OverviewStateContex import { ExtraFilterOperator } from "../../FiltersBar/types"; import useCopyToClipboard from "../../../../hooks/useCopyToClipboard"; import { CopyIcon, FilterIcon, FilterOffIcon, FocusIcon, UnfocusIcon } from "../../../../components/Main/Icons"; -import { isMacOs } from "../../../../utils/detect-device"; import TopRowMenu from "../FieldRowMenu/TopRowMenu"; +import { altKeyLabel, ctrlKeyLabel } from "../../../../utils/keyboard"; const TopStreamNames: FC = () => { const { period: { start, end } } = useTimeState(); @@ -81,13 +81,13 @@ const TopStreamNames: FC = () => { { label: "Include", icon: , - shortcut: (isMacOs() ? "Option" : "Alt") + " + Click", + shortcut: `${altKeyLabel} + Click`, onClick: () => handleAddIncludeFilter(row) }, { label: "Exclude", icon: , - shortcut: (isMacOs() ? "Cmd" : "Ctrl") + " + Click", + shortcut: `${ctrlKeyLabel} + Click`, onClick: () => handleAddExcludeFilter(row) } ], diff --git a/app/vmui/packages/vmui/src/utils/keyboard.ts b/app/vmui/packages/vmui/src/utils/keyboard.ts new file mode 100644 index 0000000000..4fda6ab056 --- /dev/null +++ b/app/vmui/packages/vmui/src/utils/keyboard.ts @@ -0,0 +1,5 @@ +import { isMacOs } from "./detect-device"; + +export const ctrlKeyLabel = isMacOs() ? "⌘" : "Ctrl"; + +export const altKeyLabel = isMacOs() ? "⌥" : "Alt"; diff --git a/docs/victorialogs/CHANGELOG.md b/docs/victorialogs/CHANGELOG.md index b4a0d2ca3a..c501d9ed11 100644 --- a/docs/victorialogs/CHANGELOG.md +++ b/docs/victorialogs/CHANGELOG.md @@ -26,6 +26,7 @@ according to the follosing docs: * FEATURE: [OpenTelemetry data ingestion](https://docs.victoriametrics.com/victorialogs/data-ingestion/opentelemetry/): reduce CPU usage by up to 10x. Thanks to @vadimalekseev for [the pull request #720](https://github.com/VictoriaMetrics/VictoriaLogs/pull/720). * FEATURE: [HTTP querying API](https://docs.victoriametrics.com/victorialogs/querying/#http-api): automatically convert the results of [`row_any()`](https://docs.victoriametrics.com/victorialogs/logsql/#row_any-stats), [`row_min()`](https://docs.victoriametrics.com/victorialogs/logsql/#row_min-stats) and [`row_max()`](https://docs.victoriametrics.com/victorialogs/logsql/#row_max-stats) stats functions to labels in [`/select/logsql/stats_query`](https://docs.victoriametrics.com/victorialogs/querying/#querying-log-stats) and [`/select/logsql/stats_query_range`](https://docs.victoriametrics.com/victorialogs/querying/#querying-log-range-stats) functions. This allows obtaining a sample of log message in alerting rules with the following query: `... | stats count() as hits, row_any(_msg) as msg_sample`. See [#81](https://github.com/VictoriaMetrics/VictoriaLogs/issues/81). * FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): show VictoriaLogs version in the vmui's footer. See [#116](https://github.com/VictoriaMetrics/VictoriaLogs/issues/116). +* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): add hotkeys to toggle series in the hit chart. * BUGFIX: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): fix mobile layout styles.