diff --git a/src/components/HelpFooter/HelpFooter.tsx b/src/components/HelpFooter/HelpFooter.tsx index b6b4fc58..d639a829 100644 --- a/src/components/HelpFooter/HelpFooter.tsx +++ b/src/components/HelpFooter/HelpFooter.tsx @@ -1,8 +1,7 @@ -import React, { useState } from 'react'; -import { Icon, useTheme2, Modal } from '@grafana/ui'; -import { config } from '@grafana/runtime'; -import { t } from '@grafana/i18n'; +import React from 'react'; +import { Icon, useTheme2 } from '@grafana/ui'; import { getHelpFooterStyles } from '../../styles/help-footer.styles'; +import { useGrafanaHelpMenu } from '../../utils/help-menu.hook'; interface HelpFooterProps { className?: string; @@ -11,59 +10,19 @@ interface HelpFooterProps { export const HelpFooter: React.FC = ({ className }) => { const theme = useTheme2(); const styles = getHelpFooterStyles(theme); - const [isHelpModalOpen, setIsHelpModalOpen] = useState(false); - const handleKeyboardShortcuts = () => { - setIsHelpModalOpen(true); - }; + // Get help menu data from Grafana's nav state + const helpMenuData = useGrafanaHelpMenu(); - const handleCloseHelpModal = () => { - setIsHelpModalOpen(false); - }; - - const helpButtons = [ - { - key: 'documentation', - label: t('helpFooter.buttons.documentation', 'Documentation'), - icon: 'file-alt' as const, - href: 'https://grafana.com/docs/grafana/latest/?utm_source=grafana_footer', - }, - { - key: 'support', - label: t('helpFooter.buttons.support', 'Support'), - icon: 'question-circle' as const, - href: 'https://grafana.com/support/?utm_source=grafana_footer', - }, - { - key: 'community', - label: t('helpFooter.buttons.community', 'Community'), - icon: 'comments-alt' as const, - href: 'https://community.grafana.com/?utm_source=grafana_footer', - }, - { - key: 'enterprise', - label: t('helpFooter.buttons.enterprise', 'Enterprise'), - icon: 'external-link-alt' as const, - href: 'https://grafana.com/products/enterprise/?utm_source=grafana_footer', - }, - { - key: 'download', - label: t('helpFooter.buttons.download', 'Download'), - icon: 'download-alt' as const, - href: 'https://grafana.com/grafana/download?utm_source=grafana_footer', - }, - { - key: 'shortcuts', - label: t('helpFooter.buttons.shortcuts', 'Shortcuts'), - icon: 'keyboard' as const, - onClick: handleKeyboardShortcuts, - }, - ]; + // Only render if we have menu items + if (helpMenuData.items.length === 0) { + return null; + } return (
- {helpButtons.map((button) => { + {helpMenuData.items.map((button) => { const ButtonComponent = button.href ? 'a' : 'button'; const buttonProps = button.href ? { @@ -87,137 +46,14 @@ export const HelpFooter: React.FC = ({ className }) => { })}
- {/* Version info */} - {config.buildInfo && ( + {/* Version info from help node subtitle */} + {helpMenuData.subtitle && (
- Grafana v{config.buildInfo.version} ({config.buildInfo.commit?.substring(0, 10) || 'unknown'}) + {helpMenuData.subtitle}
)} - - {/* Keyboard Shortcuts Modal */} - {isHelpModalOpen && ( - -
-
-

{t('helpFooter.modal.globalShortcuts', 'Global Shortcuts')}

-
-
- - ? - -
-
{t('helpFooter.modal.showAllShortcuts', 'Show all keyboard shortcuts')}
-
- - g h - -
-
{t('helpFooter.modal.goToHomeDashboard', 'Go to Home Dashboard')}
-
- - g d - -
-
{t('helpFooter.modal.goToDashboards', 'Go to Dashboards')}
-
- - esc - -
-
{t('helpFooter.modal.exitEditViews', 'Exit edit/setting views')}
-
-
- -
-

{t('helpFooter.modal.dashboardShortcuts', 'Dashboard Shortcuts')}

-
-
- - d r - -
-
{t('helpFooter.modal.refreshAllPanels', 'Refresh all panels')}
-
- - d s - -
-
{t('helpFooter.modal.dashboardSettings', 'Dashboard settings')}
-
- - d v - -
-
{t('helpFooter.modal.toggleViewMode', 'Toggle view mode')}
-
-
- -
- {t( - 'helpFooter.modal.simplifiedView', - "This is a simplified view. You can replace this with Grafana's full HelpModal component." - )} -
-
-
- )}
); }; diff --git a/src/utils/help-menu.hook.ts b/src/utils/help-menu.hook.ts new file mode 100644 index 00000000..9126e800 --- /dev/null +++ b/src/utils/help-menu.hook.ts @@ -0,0 +1,111 @@ +import { useSelector } from 'react-redux'; +import { cloneDeep } from 'lodash'; +import { config } from '@grafana/runtime'; +import { NavModelItem } from '@grafana/data'; +import { t } from '@grafana/i18n'; + +interface HelpMenuItem { + key: string; + label: string; + icon: string; + href?: string; + onClick?: () => void; +} + +interface HelpMenuData { + items: HelpMenuItem[]; + subtitle?: string; +} + +// Copied from https://github.com/grafana/grafana/blob/2b8c74d/public/app/core/components/Footer/Footer.tsx#L17 +// Get footer links. +function getFooterLinks(): NavModelItem[] { + return [ + { + text: t('nav.help/documentation', 'Documentation'), + icon: 'document-info', + url: 'https://grafana.com/docs/grafana/latest/?utm_source=grafana_pathfinder', + target: '_blank', + }, + { + text: t('nav.help/support', 'Support'), + icon: 'question-circle', + url: 'https://grafana.com/products/enterprise/?utm_source=grafana_pathfinder', + target: '_blank', + }, + { + text: t('nav.help/community', 'Community'), + icon: 'comments-alt', + url: 'https://community.grafana.com/?utm_source=grafana_pathfinder', + target: '_blank', + }, + ]; +} + +// Copied from https://github.com/grafana/grafana/blob/2b8c74d/public/app/core/components/AppChrome/MegaMenu/utils.ts#L130 +// Get edition and update links. +export function getEditionAndUpdateLinks(): NavModelItem[] { + const { buildInfo, licenseInfo } = config; + const stateInfo = licenseInfo.stateInfo ? ` (${licenseInfo.stateInfo})` : ''; + const links: NavModelItem[] = []; + + links.push({ + target: '_blank', + id: 'version', + text: `${buildInfo.edition}${stateInfo}`, + url: licenseInfo.licenseUrl, + icon: 'external-link-alt', + }); + + if (buildInfo.hasUpdate) { + links.push({ + target: '_blank', + id: 'updateVersion', + text: `New version available!`, + icon: 'download-alt', + url: 'https://grafana.com/grafana/download?utm_source=grafana_pathfinder', + }); + } + + return links; +} + +// Copied from https://github.com/grafana/grafana/blob/2b8c74d/public/app/core/components/AppChrome/MegaMenu/utils.ts#L16 +// Enrich help item. +function enrichHelpItem(helpItem: NavModelItem): NavModelItem { + let menuItems = helpItem.children || []; + + if (helpItem.id === 'help') { + helpItem.children = [ + ...menuItems, + ...getFooterLinks(), + ...getEditionAndUpdateLinks(), + // No keyboard shortcuts until Grafana exposes that for us. + ]; + } + return helpItem; +} + +export function useGrafanaHelpMenu(): HelpMenuData { + const navIndex = useSelector((state: any) => state.navIndex); + + if (!navIndex || !navIndex['help']) { + return { items: [] }; + } + + const helpNode = cloneDeep(navIndex['help']); + const enrichedHelpNode = enrichHelpItem(helpNode); + + const helpMenuItems: HelpMenuItem[] = (enrichedHelpNode.children || []).map((item) => ({ + key: item.id || item.text, + label: item.text, + icon: item.icon || 'question-circle', + href: item.url, + onClick: item.onClick, + })); + + return { + items: helpMenuItems, + subtitle: enrichedHelpNode.subTitle, + }; +}