minor refactoring to isolate the code.
CodeQL checks / Detect whether code changed (push) Has been cancelled Details
CodeQL checks / Analyze (actions) (push) Has been cancelled Details
CodeQL checks / Analyze (go) (push) Has been cancelled Details
CodeQL checks / Analyze (javascript) (push) Has been cancelled Details

This commit is contained in:
Marcus Andersson 2025-10-01 20:31:04 +02:00
parent 6584361f66
commit 28f2e12f5d
No known key found for this signature in database
GPG Key ID: 5E93670261CE6DED
2 changed files with 82 additions and 61 deletions

View File

@ -0,0 +1,78 @@
import { css } from '@emotion/css';
import { memo } from 'react';
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
import { t } from '@grafana/i18n';
import { getAppEvents } from '@grafana/runtime';
import { Dropdown, ToolbarButton, useStyles2 } from '@grafana/ui';
import { OpenExtensionSidebarEvent } from 'app/types/events';
import {
useExtensionSidebarContext,
getComponentIdFromComponentMeta,
} from '../ExtensionSidebar/ExtensionSidebarProvider';
import { TopNavBarMenu } from './TopNavBarMenu';
interface Props {
isSmallScreen: boolean;
enrichedHelpNode: NavModelItem;
}
export const HelpTopBarButton = memo(function HelpTopBarButton({ enrichedHelpNode, isSmallScreen }: Props) {
const { setDockedComponentId, dockedComponentId, availableComponents } = useExtensionSidebarContext();
const styles = useStyles2(getStyles);
if (isSmallScreen || !enrichedHelpNode.hideFromTabs || !availableComponents.has('grafana-grafanadocsplugin-app')) {
return (
<Dropdown overlay={() => <TopNavBarMenu node={enrichedHelpNode} />} placement="bottom-end">
<ToolbarButton iconOnly icon="question-circle" aria-label={t('navigation.help.aria-label', 'Help')} />
</Dropdown>
);
}
const componentId = getComponentIdFromComponentMeta('grafana-grafanadocsplugin-app', 'Grafana Pathfinder');
const isOpen = dockedComponentId === componentId;
return (
<ToolbarButton
iconOnly
icon="question-circle"
aria-label={t('navigation.help.aria-label', 'Help')}
className={isOpen ? styles.helpButtonActive : undefined}
onClick={() => {
if (isOpen) {
setDockedComponentId(undefined);
} else {
const appEvents = getAppEvents();
appEvents.publish(
new OpenExtensionSidebarEvent({
pluginId: 'grafana-grafanadocsplugin-app',
componentTitle: 'Grafana Pathfinder',
props: {
helpNode: withoutParents(enrichedHelpNode),
},
})
);
}
}}
/>
);
});
function withoutParents(node: NavModelItem): NavModelItem {
const { parentItem, ...rest } = node;
return {
...rest,
children: node.children?.map(withoutParents),
};
}
const getStyles = (theme: GrafanaTheme2) => ({
helpButtonActive: css({
borderRadius: theme.shape.radius.circle,
backgroundColor: theme.colors.primary.transparent,
border: `1px solid ${theme.colors.primary.borderTransparent}`,
color: theme.colors.text.primary,
}),
});

View File

@ -5,35 +5,30 @@ import React, { memo } from 'react';
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
import { Components } from '@grafana/e2e-selectors';
import { t } from '@grafana/i18n';
import { ScopesContextValue, getAppEvents } from '@grafana/runtime';
import { Dropdown, Icon, Stack, ToolbarButton, useStyles2 } from '@grafana/ui';
import { ScopesContextValue } from '@grafana/runtime';
import { Icon, Stack, ToolbarButton, useStyles2 } from '@grafana/ui';
import { config } from 'app/core/config';
import { MEGA_MENU_TOGGLE_ID } from 'app/core/constants';
import { useGrafana } from 'app/core/context/GrafanaContext';
import { contextSrv } from 'app/core/core';
import { useMediaQueryMinWidth } from 'app/core/hooks/useMediaQueryMinWidth';
import { HOME_NAV_ID } from 'app/core/reducers/navModel';
import { OpenExtensionSidebarEvent } from 'app/types/events';
import { useSelector } from 'app/types/store';
import { Branding } from '../../Branding/Branding';
import { Breadcrumbs } from '../../Breadcrumbs/Breadcrumbs';
import { buildBreadcrumbs } from '../../Breadcrumbs/utils';
import {
useExtensionSidebarContext,
getComponentIdFromComponentMeta,
} from '../ExtensionSidebar/ExtensionSidebarProvider';
import { ExtensionToolbarItem } from '../ExtensionSidebar/ExtensionToolbarItem';
import { HistoryContainer } from '../History/HistoryContainer';
import { enrichHelpItem } from '../MegaMenu/utils';
import { NavToolbarSeparator } from '../NavToolbar/NavToolbarSeparator';
import { QuickAdd } from '../QuickAdd/QuickAdd';
import { HelpTopBarButton } from './HelpTopBarButton';
import { InviteUserButton } from './InviteUserButton';
import { ProfileButton } from './ProfileButton';
import { SignInLink } from './SignInLink';
import { SingleTopBarActions } from './SingleTopBarActions';
import { TopNavBarMenu } from './TopNavBarMenu';
import { TopSearchBarCommandPaletteTrigger } from './TopSearchBarCommandPaletteTrigger';
import { getChromeHeaderLevelHeight } from './useChromeHeaderHeight';
@ -60,7 +55,6 @@ export const SingleTopBar = memo(function SingleTopBar({
}: Props) {
const { chrome } = useGrafana();
const state = chrome.useState();
const { setDockedComponentId, dockedComponentId, availableComponents } = useExtensionSidebarContext();
const menuDockedAndOpen = !state.chromeless && state.megaMenuDocked && state.megaMenuOpen;
const styles = useStyles2(getStyles, menuDockedAndOpen);
const navIndex = useSelector((state) => state.navIndex);
@ -104,44 +98,7 @@ export const SingleTopBar = memo(function SingleTopBar({
<TopSearchBarCommandPaletteTrigger />
{unifiedHistoryEnabled && !isSmallScreen && <HistoryContainer />}
{!isSmallScreen && <QuickAdd />}
{enrichedHelpNode &&
(enrichedHelpNode.hideFromTabs && availableComponents.has('grafana-grafanadocsplugin-app') ? (
(() => {
const componentId = getComponentIdFromComponentMeta(
'grafana-grafanadocsplugin-app',
'Grafana Pathfinder'
);
const isOpen = dockedComponentId === componentId;
return (
<ToolbarButton
iconOnly
icon="question-circle"
aria-label={t('navigation.help.aria-label', 'Help')}
className={isOpen ? styles.helpButtonActive : undefined}
onClick={() => {
if (isOpen) {
setDockedComponentId(undefined);
} else {
const appEvents = getAppEvents();
appEvents.publish(
new OpenExtensionSidebarEvent({
pluginId: 'grafana-grafanadocsplugin-app',
componentTitle: 'Grafana Pathfinder',
props: {
helpNode: withoutParents(enrichedHelpNode),
},
})
);
}
}}
/>
);
})()
) : (
<Dropdown overlay={() => <TopNavBarMenu node={enrichedHelpNode} />} placement="bottom-end">
<ToolbarButton iconOnly icon="question-circle" aria-label={t('navigation.help.aria-label', 'Help')} />
</Dropdown>
))}
{enrichedHelpNode && <HelpTopBarButton enrichedHelpNode={enrichedHelpNode} isSmallScreen={isSmallScreen} />}
<NavToolbarSeparator />
{!isSmallScreen && <ExtensionToolbarItem compact={isSmallScreen} />}
{!showToolbarLevel && actions}
@ -157,14 +114,6 @@ export const SingleTopBar = memo(function SingleTopBar({
);
});
function withoutParents(node: NavModelItem): NavModelItem {
const { parentItem, ...rest } = node;
return {
...rest,
children: node.children?.map(withoutParents),
};
}
const getStyles = (theme: GrafanaTheme2, menuDockedAndOpen: boolean) => ({
layout: css({
height: getChromeHeaderLevelHeight(),
@ -193,10 +142,4 @@ const getStyles = (theme: GrafanaTheme2, menuDockedAndOpen: boolean) => ({
display: 'none',
},
}),
helpButtonActive: css({
borderRadius: theme.shape.radius.circle,
backgroundColor: theme.colors.primary.transparent,
border: `1px solid ${theme.colors.primary.borderTransparent}`,
color: theme.colors.text.primary,
}),
});