Skip to content

Commit d46e391

Browse files
Navigation: move connections + integrations to be a top level item (grafana#58902)
* move connections + integrations to be a top level item * add a test to check we can move apps to the root * split out movePlugin logic into a separate function * fix linting * rename movePlugin -> addPluginToSection
1 parent 48c34d3 commit d46e391

File tree

4 files changed

+37
-8
lines changed

4 files changed

+37
-8
lines changed

pkg/services/navtree/models.go

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const (
3636
)
3737

3838
const (
39+
NavIDRoot = "root"
3940
NavIDDashboards = "dashboards"
4041
NavIDDashboardsBrowse = "dashboards/browse"
4142
NavIDCfg = "cfg" // NavIDCfg is the id for org configuration navigation node

pkg/services/navtree/navtreeimpl/applinks.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ func (s *ServiceImpl) processAppPlugin(plugin plugins.PluginDTO, c *models.ReqCo
170170
}
171171
appLink.Children = childrenWithoutDefault
172172

173+
s.addPluginToSection(c, treeRoot, plugin, appLink)
174+
175+
return nil
176+
}
177+
178+
func (s *ServiceImpl) addPluginToSection(c *models.ReqContext, treeRoot *navtree.NavTreeRoot, plugin plugins.PluginDTO, appLink *navtree.NavLink) {
173179
// Handle moving apps into specific navtree sections
174180
alertingNode := treeRoot.FindById(navtree.NavIDAlerting)
175181
sectionID := navtree.NavIDApps
@@ -183,7 +189,9 @@ func (s *ServiceImpl) processAppPlugin(plugin plugins.PluginDTO, c *models.ReqCo
183189
}
184190
}
185191

186-
if navNode := treeRoot.FindById(sectionID); navNode != nil {
192+
if sectionID == navtree.NavIDRoot {
193+
treeRoot.AddSection(appLink)
194+
} else if navNode := treeRoot.FindById(sectionID); navNode != nil {
187195
navNode.Children = append(navNode.Children, appLink)
188196
} else {
189197
switch sectionID {
@@ -227,8 +235,6 @@ func (s *ServiceImpl) processAppPlugin(plugin plugins.PluginDTO, c *models.ReqCo
227235
s.log.Error("Plugin app nav id not found", "pluginId", plugin.ID, "navId", sectionID)
228236
}
229237
}
230-
231-
return nil
232238
}
233239

234240
func (s *ServiceImpl) hasAccessToInclude(c *models.ReqContext, pluginID string) func(include *plugins.Includes) bool {
@@ -256,6 +262,7 @@ func (s *ServiceImpl) readNavigationSettings() {
256262
"grafana-incident-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 2, Text: "Incident"},
257263
"grafana-ml-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 3, Text: "Machine Learning"},
258264
"grafana-cloud-link-app": {SectionID: navtree.NavIDCfg},
265+
"grafana-easystart-app": {SectionID: navtree.NavIDRoot, SortWeight: navtree.WeightSavedItems + 1, Text: "Connections"},
259266
}
260267

261268
s.navigationAppPathConfig = map[string]NavigationAppConfig{

pkg/services/navtree/navtreeimpl/applinks_test.go

+24
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,30 @@ func TestAddAppLinks(t *testing.T) {
147147
require.Equal(t, "Page2", app1Node.Children[0].Text)
148148
})
149149

150+
// This can be done by using `[navigation.app_sections]` in the INI config
151+
t.Run("Should move apps that have root nav id configured to the root", func(t *testing.T) {
152+
service.features = featuremgmt.WithFeatures(featuremgmt.FlagTopnav)
153+
service.navigationAppConfig = map[string]NavigationAppConfig{
154+
"test-app1": {SectionID: navtree.NavIDRoot},
155+
}
156+
157+
treeRoot := navtree.NavTreeRoot{}
158+
159+
err := service.addAppLinks(&treeRoot, reqCtx)
160+
require.NoError(t, err)
161+
162+
// Check if the plugin gets moved to the root
163+
require.Len(t, treeRoot.Children, 2)
164+
require.Equal(t, "plugin-page-test-app1", treeRoot.Children[0].Id)
165+
166+
// Check if it is not under the "Apps" section anymore
167+
appsNode := treeRoot.FindById(navtree.NavIDApps)
168+
require.NotNil(t, appsNode)
169+
require.Len(t, appsNode.Children, 2)
170+
require.Equal(t, "plugin-page-test-app2", appsNode.Children[0].Id)
171+
require.Equal(t, "plugin-page-test-app3", appsNode.Children[1].Id)
172+
})
173+
150174
// This can be done by using `[navigation.app_sections]` in the INI config
151175
t.Run("Should move apps that have specific nav id configured to correct section", func(t *testing.T) {
152176
service.features = featuremgmt.WithFeatures(featuremgmt.FlagTopnav)

public/app/core/components/MegaMenu/MegaMenu.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,14 @@ export const MegaMenu = React.memo<Props>(({ onClose, searchBarHidden }) => {
2525
const navTree = cloneDeep(navBarTree);
2626

2727
const coreItems = navTree
28-
.filter((item) => item.section === NavSection.Core)
29-
.map((item) => enrichWithInteractionTracking(item, true));
30-
const pluginItems = navTree
31-
.filter((item) => item.section === NavSection.Plugin)
28+
.filter((item) => item.section === NavSection.Core || item.section === NavSection.Plugin)
3229
.map((item) => enrichWithInteractionTracking(item, true));
3330
const configItems = enrichConfigItems(
3431
navTree.filter((item) => item.section === NavSection.Config && item && item.id !== 'help' && item.id !== 'profile'),
3532
location
3633
).map((item) => enrichWithInteractionTracking(item, true));
3734

38-
const navItems = [...coreItems, ...pluginItems, ...configItems];
35+
const navItems = [...coreItems, ...configItems];
3936

4037
const activeItem = getActiveItem(navItems, location.pathname);
4138

0 commit comments

Comments
 (0)