From a92c8145f18eba15e77569ca7ce9aa4de6c0c0a6 Mon Sep 17 00:00:00 2001 From: Carl Bergquist Date: Thu, 30 Jan 2025 14:43:26 +0100 Subject: [PATCH] TopNav: Move news into profile menu (#99535) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * remove news icon from topnav Signed-off-by: bergquist * TopNav: Move rss feed and kiosk action into profile menu * Update language keys * Update * review fixes * Update * Update --------- Signed-off-by: bergquist Co-authored-by: Torkel Ödegaard --- .betterer.results | 11 +-- .../AppChrome/News/NewsContainer.test.tsx | 19 ----- .../AppChrome/News/NewsContainer.tsx | 84 ------------------- .../components/AppChrome/News/NewsDrawer.tsx | 78 +++++++++++++++++ .../AppChrome/TopBar/ProfileButton.tsx | 71 ++++++++++++++++ .../AppChrome/TopBar/SingleTopBar.tsx | 23 +---- .../AppChrome/TopBar/TopNavBarMenu.tsx | 4 +- public/locales/en-US/grafana.json | 3 +- public/locales/pseudo-LOCALE/grafana.json | 3 +- 9 files changed, 164 insertions(+), 132 deletions(-) delete mode 100644 public/app/core/components/AppChrome/News/NewsContainer.test.tsx delete mode 100644 public/app/core/components/AppChrome/News/NewsContainer.tsx create mode 100644 public/app/core/components/AppChrome/News/NewsDrawer.tsx create mode 100644 public/app/core/components/AppChrome/TopBar/ProfileButton.tsx diff --git a/.betterer.results b/.betterer.results index 01d1a68627b..8e643b38615 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1003,9 +1003,8 @@ exports[`better eslint`] = { "public/app/core/components/AppChrome/MegaMenu/MegaMenuItem.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] ], - "public/app/core/components/AppChrome/News/NewsContainer.tsx:5381": [ - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"] + "public/app/core/components/AppChrome/News/NewsDrawer.tsx:5381": [ + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] ], "public/app/core/components/AppChrome/News/NewsWrapper.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] @@ -1016,10 +1015,12 @@ exports[`better eslint`] = { "public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] ], + "public/app/core/components/AppChrome/TopBar/ProfileButton.tsx:5381": [ + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] + ], "public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"] + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"] ], "public/app/core/components/AppChrome/TopBar/TopSearchBarCommandPaletteTrigger.tsx:5381": [ [0, 0, 0, "\'@grafana/ui/src/themes/mixins\' import is restricted from being used by a pattern. Import from the public export instead.", "0"] diff --git a/public/app/core/components/AppChrome/News/NewsContainer.test.tsx b/public/app/core/components/AppChrome/News/NewsContainer.test.tsx deleted file mode 100644 index 3b1ed747283..00000000000 --- a/public/app/core/components/AppChrome/News/NewsContainer.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; - -import { NewsContainer } from './NewsContainer'; - -const setup = () => { - const { container } = render(); - - return { container }; -}; - -describe('News', () => { - it('should render the drawer when the drawer button is clicked', async () => { - setup(); - - await userEvent.click(screen.getByRole('button')); - expect(screen.getByText('Latest from the blog')).toBeInTheDocument(); - }); -}); diff --git a/public/app/core/components/AppChrome/News/NewsContainer.tsx b/public/app/core/components/AppChrome/News/NewsContainer.tsx deleted file mode 100644 index 2d4cec5a628..00000000000 --- a/public/app/core/components/AppChrome/News/NewsContainer.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { css } from '@emotion/css'; -import { useToggle } from 'react-use'; - -import { GrafanaTheme2 } from '@grafana/data'; -import { selectors } from '@grafana/e2e-selectors'; -import { IconButton, Drawer, ToolbarButton, useStyles2, Text } from '@grafana/ui'; -import { t } from 'app/core/internationalization'; -import { DEFAULT_FEED_URL } from 'app/plugins/panel/news/constants'; - -import { NewsWrapper } from './NewsWrapper'; - -interface NewsContainerProps { - className?: string; -} - -export function NewsContainer({ className }: NewsContainerProps) { - const [showNewsDrawer, onToggleShowNewsDrawer] = useToggle(false); - const styles = useStyles2(getStyles); - - return ( - <> - - {showNewsDrawer && ( - - {t('news.title', 'Latest from the blog')} - - Grot reading news - -
- -
- - } - onClose={onToggleShowNewsDrawer} - size="md" - > - -
- )} - - ); -} - -const getStyles = (theme: GrafanaTheme2) => { - return { - title: css({ - display: `flex`, - alignItems: `center`, - justifyContent: `center`, - gap: theme.spacing(2), - borderBottom: `1px solid ${theme.colors.border.weak}`, - }), - grot: css({ - display: `flex`, - alignItems: `center`, - justifyContent: `center`, - padding: theme.spacing(2, 0), - - img: { - width: `75px`, - height: `75px`, - }, - }), - actions: css({ - position: 'absolute', - right: theme.spacing(1), - top: theme.spacing(2), - }), - }; -}; diff --git a/public/app/core/components/AppChrome/News/NewsDrawer.tsx b/public/app/core/components/AppChrome/News/NewsDrawer.tsx new file mode 100644 index 00000000000..7211823430d --- /dev/null +++ b/public/app/core/components/AppChrome/News/NewsDrawer.tsx @@ -0,0 +1,78 @@ +import { css } from '@emotion/css'; + +import { GrafanaTheme2 } from '@grafana/data'; +import { selectors } from '@grafana/e2e-selectors'; +import { IconButton, Drawer, useStyles2, Text } from '@grafana/ui'; +import { t } from 'app/core/internationalization'; +import { DEFAULT_FEED_URL } from 'app/plugins/panel/news/constants'; + +import { NewsWrapper } from './NewsWrapper'; + +interface NewsContainerProps { + className?: string; + onClose: () => void; +} + +export function NewsContainer({ onClose }: NewsContainerProps) { + const styles = useStyles2(getStyles); + + return ( + + {t('news.title', 'Latest from the blog')} + + Grot reading news + +
+ +
+ + } + onClose={onClose} + size="md" + > + +
+ ); +} + +const getStyles = (theme: GrafanaTheme2) => { + return { + title: css({ + display: `flex`, + alignItems: `center`, + justifyContent: `center`, + gap: theme.spacing(2), + borderBottom: `1px solid ${theme.colors.border.weak}`, + }), + grot: css({ + display: `flex`, + alignItems: `center`, + justifyContent: `center`, + padding: theme.spacing(2, 0), + + img: { + width: `75px`, + height: `75px`, + }, + }), + actions: css({ + position: 'absolute', + right: theme.spacing(1), + top: theme.spacing(2), + }), + }; +}; diff --git a/public/app/core/components/AppChrome/TopBar/ProfileButton.tsx b/public/app/core/components/AppChrome/TopBar/ProfileButton.tsx new file mode 100644 index 00000000000..3faa5f24876 --- /dev/null +++ b/public/app/core/components/AppChrome/TopBar/ProfileButton.tsx @@ -0,0 +1,71 @@ +import { css } from '@emotion/css'; +import { cloneDeep } from 'lodash'; +import { useToggle } from 'react-use'; + +import { GrafanaTheme2, NavModelItem } from '@grafana/data'; +import { config } from '@grafana/runtime'; +import { Dropdown, Menu, MenuItem, ToolbarButton, useStyles2 } from '@grafana/ui'; +import { contextSrv } from 'app/core/core'; +import { t } from 'app/core/internationalization'; + +import { enrichWithInteractionTracking } from '../MegaMenu/utils'; +import { NewsContainer } from '../News/NewsDrawer'; + +import { TopNavBarMenu } from './TopNavBarMenu'; + +export interface Props { + profileNode: NavModelItem; +} + +export function ProfileButton({ profileNode }: Props) { + const styles = useStyles2(getStyles); + const node = enrichWithInteractionTracking(cloneDeep(profileNode), false); + const [showNewsDrawer, onToggleShowNewsDrawer] = useToggle(false); + + if (!node) { + return null; + } + + const renderMenu = () => ( + + {config.newsFeedEnabled && ( + <> + + + + )} + + ); + + return ( + <> + + + + {showNewsDrawer && } + + ); +} + +const getStyles = (theme: GrafanaTheme2) => { + return { + profileButton: css({ + padding: theme.spacing(0, 0.5), + img: { + borderRadius: theme.shape.radius.circle, + height: '24px', + marginRight: 0, + width: '24px', + }, + }), + }; +}; diff --git a/public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx b/public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx index 819ab7371af..225db772a11 100644 --- a/public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx +++ b/public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx @@ -16,10 +16,10 @@ import { Breadcrumbs } from '../../Breadcrumbs/Breadcrumbs'; import { buildBreadcrumbs } from '../../Breadcrumbs/utils'; import { HistoryContainer } from '../History/HistoryContainer'; import { enrichHelpItem } from '../MegaMenu/utils'; -import { NewsContainer } from '../News/NewsContainer'; import { QuickAdd } from '../QuickAdd/QuickAdd'; import { TOP_BAR_LEVEL_HEIGHT } from '../types'; +import { ProfileButton } from './ProfileButton'; import { SignInLink } from './SignInLink'; import { TopNavBarMenu } from './TopNavBarMenu'; import { TopSearchBarCommandPaletteTrigger } from './TopSearchBarCommandPaletteTrigger'; @@ -80,7 +80,6 @@ export const SingleTopBar = memo(function SingleTopBar({ )} - {config.newsFeedEnabled && } {!contextSrv.user.isSignedIn && } - {profileNode && ( - } placement="bottom-end"> - - - )} + {profileNode && } ); @@ -132,15 +122,6 @@ const getStyles = (theme: GrafanaTheme2, menuDockedAndOpen: boolean) => ({ height: theme.spacing(3), width: theme.spacing(3), }), - profileButton: css({ - padding: theme.spacing(0, 0.5), - img: { - borderRadius: theme.shape.radius.circle, - height: '24px', - marginRight: 0, - width: '24px', - }, - }), kioskToggle: css({ [theme.breakpoints.down('lg')]: { display: 'none', diff --git a/public/app/core/components/AppChrome/TopBar/TopNavBarMenu.tsx b/public/app/core/components/AppChrome/TopBar/TopNavBarMenu.tsx index 27abaf86a77..7afb4c50bcc 100644 --- a/public/app/core/components/AppChrome/TopBar/TopNavBarMenu.tsx +++ b/public/app/core/components/AppChrome/TopBar/TopNavBarMenu.tsx @@ -8,9 +8,10 @@ import { enrichWithInteractionTracking } from '../MegaMenu/utils'; export interface TopNavBarMenuProps { node: NavModelItem; + children?: React.ReactNode; } -export function TopNavBarMenu({ node: nodePlain }: TopNavBarMenuProps) { +export function TopNavBarMenu({ node: nodePlain, children }: TopNavBarMenuProps) { const styles = useStyles2(getStyles); const node = enrichWithInteractionTracking(cloneDeep(nodePlain), false); @@ -37,6 +38,7 @@ export function TopNavBarMenu({ node: nodePlain }: TopNavBarMenuProps) { ); })} + {children} ); } diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 6f9cda10abe..7781727270f 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -2430,7 +2430,8 @@ "list-label": "Navigation", "open": "Open menu", "undock": "Undock menu" - } + }, + "rss-button": "Latest from the blog" }, "news": { "drawer": { diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index 6b3f2d081a7..006e0f4a07f 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -2430,7 +2430,8 @@ "list-label": "Ńävįģäŧįőʼn", "open": "Øpęʼn męʼnū", "undock": "Ůʼnđőčĸ męʼnū" - } + }, + "rss-button": "Ŀäŧęşŧ ƒřőm ŧĥę þľőģ" }, "news": { "drawer": {