mirror of
https://github.com/grafana/grafana.git
synced 2025-01-08 23:23:45 -06:00
Bookmarks: Move building logic to the Frontend (#91849)
This commit is contained in:
parent
d6e793b31e
commit
42efb14989
@ -169,14 +169,12 @@ func (s *ServiceImpl) GetNavTree(c *contextmodel.ReqContext, prefs *pref.Prefere
|
||||
}
|
||||
|
||||
if s.features.IsEnabled(c.Req.Context(), featuremgmt.FlagPinNavItems) {
|
||||
bookmarks := s.buildBookmarksNavLinks(prefs, treeRoot)
|
||||
|
||||
treeRoot.AddSection(&navtree.NavLink{
|
||||
Text: "Bookmarks",
|
||||
Id: navtree.NavIDBookmarks,
|
||||
Icon: "bookmark",
|
||||
SortWeight: navtree.WeightBookmarks,
|
||||
Children: bookmarks,
|
||||
Children: []*navtree.NavLink{},
|
||||
EmptyMessageId: "bookmarks-empty",
|
||||
Url: s.cfg.AppSubURL + "/bookmarks",
|
||||
})
|
||||
@ -335,39 +333,6 @@ func (s *ServiceImpl) buildStarredItemsNavLinks(c *contextmodel.ReqContext) ([]*
|
||||
|
||||
return starredItemsChildNavs, nil
|
||||
}
|
||||
func (s *ServiceImpl) buildBookmarksNavLinks(prefs *pref.Preference, treeRoot *navtree.NavTreeRoot) []*navtree.NavLink {
|
||||
bookmarksChildNavs := []*navtree.NavLink{}
|
||||
|
||||
bookmarkUrls := prefs.JSONData.Navbar.BookmarkUrls
|
||||
|
||||
if len(bookmarkUrls) > 0 {
|
||||
for _, url := range bookmarkUrls {
|
||||
item := treeRoot.FindByURL(url)
|
||||
if item != nil {
|
||||
bookmarksChildNavs = append(bookmarksChildNavs, &navtree.NavLink{
|
||||
Id: item.Id,
|
||||
Text: item.Text,
|
||||
SubTitle: item.SubTitle,
|
||||
Icon: item.Icon,
|
||||
Img: item.Img,
|
||||
Url: item.Url,
|
||||
Target: item.Target,
|
||||
HideFromTabs: item.HideFromTabs,
|
||||
RoundIcon: item.RoundIcon,
|
||||
IsSection: item.IsSection,
|
||||
HighlightText: item.HighlightText,
|
||||
HighlightID: item.HighlightID,
|
||||
PluginID: item.PluginID,
|
||||
IsCreateAction: item.IsCreateAction,
|
||||
Keywords: item.Keywords,
|
||||
ParentItem: &navtree.NavLink{Id: navtree.NavIDBookmarks},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bookmarksChildNavs
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) buildDashboardNavLinks(c *contextmodel.ReqContext) []*navtree.NavLink {
|
||||
hasAccess := ac.HasAccess(s.accessControl, c)
|
||||
|
@ -15,7 +15,7 @@ import { useDispatch, useSelector } from 'app/types';
|
||||
|
||||
import { MegaMenuItem } from './MegaMenuItem';
|
||||
import { usePinnedItems } from './hooks';
|
||||
import { enrichWithInteractionTracking, getActiveItem } from './utils';
|
||||
import { enrichWithInteractionTracking, findByUrl, getActiveItem } from './utils';
|
||||
|
||||
export const MENU_WIDTH = '300px';
|
||||
|
||||
@ -39,6 +39,26 @@ export const MegaMenu = memo(
|
||||
.filter((item) => item.id !== 'profile' && item.id !== 'help')
|
||||
.map((item) => enrichWithInteractionTracking(item, state.megaMenuDocked));
|
||||
|
||||
if (config.featureToggles.pinNavItems) {
|
||||
const bookmarksItem = findByUrl(navItems, '/bookmarks');
|
||||
if (bookmarksItem) {
|
||||
// Add children to the bookmarks section
|
||||
bookmarksItem.children = pinnedItems.reduce((acc: NavModelItem[], url) => {
|
||||
const item = findByUrl(navItems, url);
|
||||
if (!item) {
|
||||
return acc;
|
||||
}
|
||||
acc.push({
|
||||
id: item.id,
|
||||
text: item.text,
|
||||
url: item.url,
|
||||
parentItem: { id: 'bookmarks', text: 'Bookmarks' },
|
||||
});
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
}
|
||||
|
||||
const activeItem = getActiveItem(navItems, state.sectionNav.node, location.pathname);
|
||||
|
||||
const handleDockedMenu = () => {
|
||||
|
@ -1,7 +1,50 @@
|
||||
import { NavModelItem } from '@grafana/data';
|
||||
import { ContextSrv, setContextSrv } from 'app/core/services/context_srv';
|
||||
|
||||
import { enrichHelpItem, getActiveItem } from './utils';
|
||||
import { enrichHelpItem, getActiveItem, findByUrl } from './utils';
|
||||
|
||||
const starredDashboardUid = 'foo';
|
||||
const mockNavTree: NavModelItem[] = [
|
||||
{
|
||||
text: 'Item',
|
||||
url: '/item',
|
||||
id: 'item',
|
||||
},
|
||||
{
|
||||
text: 'Item with children',
|
||||
url: '/itemWithChildren',
|
||||
id: 'item-with-children',
|
||||
children: [
|
||||
{
|
||||
text: 'Child',
|
||||
url: '/child',
|
||||
id: 'child',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Base',
|
||||
url: '/',
|
||||
id: 'home',
|
||||
},
|
||||
{
|
||||
text: 'Starred',
|
||||
url: '/dashboards?starred',
|
||||
id: 'starred',
|
||||
children: [
|
||||
{
|
||||
id: `starred/${starredDashboardUid}`,
|
||||
text: 'Lazy Loading',
|
||||
url: `/d/${starredDashboardUid}/some-name`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Dashboards',
|
||||
url: '/dashboards',
|
||||
id: 'dashboards',
|
||||
},
|
||||
];
|
||||
|
||||
jest.mock('../../../app_events', () => ({
|
||||
publish: jest.fn(),
|
||||
@ -45,49 +88,6 @@ describe('enrichConfigItems', () => {
|
||||
});
|
||||
|
||||
describe('getActiveItem', () => {
|
||||
const starredDashboardUid = 'foo';
|
||||
const mockNavTree: NavModelItem[] = [
|
||||
{
|
||||
text: 'Item',
|
||||
url: '/item',
|
||||
id: 'item',
|
||||
},
|
||||
{
|
||||
text: 'Item with children',
|
||||
url: '/itemWithChildren',
|
||||
id: 'item-with-children',
|
||||
children: [
|
||||
{
|
||||
text: 'Child',
|
||||
url: '/child',
|
||||
id: 'child',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Base',
|
||||
url: '/',
|
||||
id: 'home',
|
||||
},
|
||||
{
|
||||
text: 'Starred',
|
||||
url: '/dashboards?starred',
|
||||
id: 'starred',
|
||||
children: [
|
||||
{
|
||||
id: `starred/${starredDashboardUid}`,
|
||||
text: 'Lazy Loading',
|
||||
url: `/d/${starredDashboardUid}/some-name`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Dashboards',
|
||||
url: '/dashboards',
|
||||
id: 'dashboards',
|
||||
},
|
||||
];
|
||||
|
||||
it('returns an exact match at the top level', () => {
|
||||
const mockPage: NavModelItem = {
|
||||
text: 'Some current page',
|
||||
@ -124,3 +124,25 @@ describe('getActiveItem', () => {
|
||||
expect(getActiveItem(mockNavTree, mockPage, '/')?.id).toEqual('home');
|
||||
});
|
||||
});
|
||||
|
||||
describe('findByUrl', () => {
|
||||
it('returns the correct item at the top level', () => {
|
||||
expect(findByUrl(mockNavTree, '/item')).toEqual({
|
||||
text: 'Item',
|
||||
url: '/item',
|
||||
id: 'item',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the correct child item', () => {
|
||||
expect(findByUrl(mockNavTree, '/child')).toEqual({
|
||||
text: 'Child',
|
||||
url: '/child',
|
||||
id: 'child',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns null if no item found', () => {
|
||||
expect(findByUrl(mockNavTree, '/no-item')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user