diff --git a/public/app/core/components/NavBar/NavBar.tsx b/public/app/core/components/NavBar/NavBar.tsx index a6eb62b503f..b1f9bb86589 100644 --- a/public/app/core/components/NavBar/NavBar.tsx +++ b/public/app/core/components/NavBar/NavBar.tsx @@ -1,4 +1,5 @@ import React, { useState } from 'react'; +import { connect, ConnectedProps } from 'react-redux'; import { useLocation } from 'react-router-dom'; import { css, cx } from '@emotion/css'; import { cloneDeep } from 'lodash'; @@ -7,7 +8,7 @@ import { Icon, IconName, useTheme2 } from '@grafana/ui'; import { locationService } from '@grafana/runtime'; import { Branding } from 'app/core/components/Branding/Branding'; import config from 'app/core/config'; -import { KioskMode } from 'app/types'; +import { StoreState, KioskMode } from 'app/types'; import { enrichConfigItems, getActiveItem, isMatchOrChildMatch, isSearchActive, SEARCH_ITEM_ID } from './utils'; import { OrgSwitcher } from '../OrgSwitcher'; import NavBarItem from './NavBarItem'; @@ -28,7 +29,17 @@ const searchItem: NavModelItem = { icon: 'search', }; -export const NavBar = React.memo(() => { +const mapStateToProps = (state: StoreState) => ({ + navBarTree: state.navBarTree, +}); + +const mapDispatchToProps = {}; + +const connector = connect(mapStateToProps, mapDispatchToProps); + +export interface Props extends ConnectedProps {} + +export const NavBarUnconnected = React.memo(({ navBarTree }: Props) => { const theme = useTheme2(); const styles = getStyles(theme); const location = useLocation(); @@ -38,7 +49,7 @@ export const NavBar = React.memo(() => { const toggleSwitcherModal = () => { setShowSwitcherModal(!showSwitcherModal); }; - const navTree: NavModelItem[] = cloneDeep(config.bootData.navTree); + const navTree = cloneDeep(navBarTree); const topItems = navTree.filter((item) => item.section === NavSection.Core); const bottomItems = enrichConfigItems( navTree.filter((item) => item.section === NavSection.Config), @@ -109,7 +120,9 @@ export const NavBar = React.memo(() => { ); }); -NavBar.displayName = 'NavBar'; +NavBarUnconnected.displayName = 'NavBar'; + +export const NavBar = connector(NavBarUnconnected); const getStyles = (theme: GrafanaTheme2) => ({ search: css` diff --git a/public/app/core/components/NavBar/NavBarNext.tsx b/public/app/core/components/NavBar/NavBarNext.tsx index 5cfd043f6b1..b3f04cd8b86 100644 --- a/public/app/core/components/NavBar/NavBarNext.tsx +++ b/public/app/core/components/NavBar/NavBarNext.tsx @@ -5,8 +5,7 @@ import { cloneDeep } from 'lodash'; import { GrafanaTheme2, NavModelItem, NavSection } from '@grafana/data'; import { Icon, IconName, useTheme2 } from '@grafana/ui'; import { locationService } from '@grafana/runtime'; -import config from 'app/core/config'; -import { KioskMode } from 'app/types'; +import { KioskMode, StoreState } from 'app/types'; import { enrichConfigItems, getActiveItem, isMatchOrChildMatch, isSearchActive, SEARCH_ITEM_ID } from './utils'; import { OrgSwitcher } from '../OrgSwitcher'; import { NavBarSection } from './NavBarSection'; @@ -14,6 +13,7 @@ import { NavBarMenu } from './NavBarMenu'; import NavBarItem from './NavBarItem'; import { NavBarItemWithoutMenu } from './NavBarItemWithoutMenu'; import { Branding } from '../Branding/Branding'; +import { connect, ConnectedProps } from 'react-redux'; const onOpenSearch = () => { locationService.partial({ search: 'open' }); @@ -26,7 +26,17 @@ const searchItem: NavModelItem = { icon: 'search', }; -export const NavBarNext = React.memo(() => { +const mapStateToProps = (state: StoreState) => ({ + navBarTree: state.navBarTree, +}); + +const mapDispatchToProps = {}; + +const connector = connect(mapStateToProps, mapDispatchToProps); + +export interface Props extends ConnectedProps {} + +export const NavBarNextUnconnected = React.memo(({ navBarTree }: Props) => { const theme = useTheme2(); const styles = getStyles(theme); const location = useLocation(); @@ -36,7 +46,7 @@ export const NavBarNext = React.memo(() => { const toggleSwitcherModal = () => { setShowSwitcherModal(!showSwitcherModal); }; - const navTree: NavModelItem[] = cloneDeep(config.bootData.navTree); + const navTree = cloneDeep(navBarTree); const coreItems = navTree.filter((item) => item.section === NavSection.Core); const pluginItems = navTree.filter((item) => item.section === NavSection.Plugin); const configItems = enrichConfigItems( @@ -118,7 +128,9 @@ export const NavBarNext = React.memo(() => { ); }); -NavBarNext.displayName = 'NavBar'; +NavBarNextUnconnected.displayName = 'NavBarNext'; + +export const NavBarNext = connector(NavBarNextUnconnected); const getStyles = (theme: GrafanaTheme2) => ({ search: css` diff --git a/public/app/core/reducers/index.ts b/public/app/core/reducers/index.ts index 92d9a4f55cd..8787fb2e440 100644 --- a/public/app/core/reducers/index.ts +++ b/public/app/core/reducers/index.ts @@ -1,7 +1,9 @@ import { navIndexReducer as navIndex } from './navModel'; +import { navTreeReducer as navBarTree } from './navBarTree'; import { appNotificationsReducer as appNotifications } from './appNotification'; export default { + navBarTree, navIndex, appNotifications, }; diff --git a/public/app/core/reducers/navBarTree.ts b/public/app/core/reducers/navBarTree.ts new file mode 100644 index 00000000000..538e7ab0570 --- /dev/null +++ b/public/app/core/reducers/navBarTree.ts @@ -0,0 +1,15 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { NavModelItem } from '@grafana/data'; +import config from 'app/core/config'; + +export const initialState: NavModelItem[] = config.bootData.navTree; + +const navTreeSlice = createSlice({ + name: 'navBarTree', + initialState, + reducers: {}, +}); + +export const {} = navTreeSlice.actions; + +export const navTreeReducer = navTreeSlice.reducer;