[v9.3.x] Nav: Split Admin into three sections for new IA (#58974)
Nav: Split Admin into three sections for new IA (#58229)
* start to split admin into two sections
* most of new admin nav implemented
* landing pages
* hide admin for non-admins
* update admin redirects if not topnav
* clean up
* updated IA for admin (still WIP)
* move plugin pages into correct admin sections
* fix backend unit test
* move correlations into the correct section
* add translations for admin sections
Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
(cherry picked from commit 5978dc138e)
Co-authored-by: Josh Hunt <joshhunt@users.noreply.github.com>
This commit is contained in:
co-authored by
Josh Hunt
parent
e07f115f98
commit
f35ab2f79d
@@ -41,6 +41,9 @@ const (
|
||||
NavIDDashboardsBrowse = "dashboards/browse"
|
||||
NavIDCfg = "cfg" // NavIDCfg is the id for org configuration navigation node
|
||||
NavIDAdmin = "admin"
|
||||
NavIDAdminGeneral = "admin/general"
|
||||
NavIDAdminPlugins = "admin/plugins"
|
||||
NavIDAdminAccess = "admin/access"
|
||||
NavIDAlertsAndIncidents = "alerts-and-incidents"
|
||||
NavIDAlerting = "alerting"
|
||||
NavIDMonitoring = "monitoring"
|
||||
@@ -111,22 +114,7 @@ func (root *NavTreeRoot) RemoveEmptySectionsAndApplyNewInformationArchitecture(t
|
||||
}
|
||||
|
||||
if topNavEnabled {
|
||||
orgAdminNode := root.FindById(NavIDCfg)
|
||||
|
||||
if orgAdminNode != nil {
|
||||
orgAdminNode.Url = "/admin"
|
||||
orgAdminNode.Text = "Administration"
|
||||
}
|
||||
|
||||
if serverAdminNode := root.FindById(NavIDAdmin); serverAdminNode != nil {
|
||||
serverAdminNode.Url = "/admin/server"
|
||||
serverAdminNode.SortWeight = 0
|
||||
|
||||
if orgAdminNode != nil {
|
||||
orgAdminNode.Children = append(orgAdminNode.Children, serverAdminNode)
|
||||
root.RemoveSection(serverAdminNode)
|
||||
}
|
||||
}
|
||||
ApplyAdminIA(root)
|
||||
|
||||
// Move reports into dashboards
|
||||
if reports := root.FindById(NavIDReporting); reports != nil {
|
||||
@@ -181,6 +169,99 @@ func Sort(nodes []*NavLink) {
|
||||
}
|
||||
}
|
||||
|
||||
func ApplyAdminIA(root *NavTreeRoot) {
|
||||
orgAdminNode := root.FindById(NavIDCfg)
|
||||
|
||||
if orgAdminNode != nil {
|
||||
orgAdminNode.Url = "/admin"
|
||||
orgAdminNode.Text = "Administration"
|
||||
|
||||
generalNodeLinks := []*NavLink{}
|
||||
pluginsNodeLinks := []*NavLink{}
|
||||
accessNodeLinks := []*NavLink{}
|
||||
|
||||
generalNodeLinks = AppendIfNotNil(generalNodeLinks, root.FindById("upgrading"))
|
||||
if orgSettings := root.FindById("org-settings"); orgSettings != nil {
|
||||
orgSettings.Text = "Default preferences"
|
||||
generalNodeLinks = append(generalNodeLinks, orgSettings)
|
||||
}
|
||||
generalNodeLinks = AppendIfNotNil(generalNodeLinks, root.FindById("global-orgs"))
|
||||
generalNodeLinks = AppendIfNotNil(generalNodeLinks, root.FindById("server-settings"))
|
||||
|
||||
pluginsNodeLinks = AppendIfNotNil(pluginsNodeLinks, root.FindById("plugins"))
|
||||
pluginsNodeLinks = AppendIfNotNil(pluginsNodeLinks, root.FindById("datasources"))
|
||||
pluginsNodeLinks = AppendIfNotNil(pluginsNodeLinks, root.FindById("correlations"))
|
||||
pluginsNodeLinks = AppendIfNotNil(pluginsNodeLinks, root.FindById("plugin-page-grafana-cloud-link-app"))
|
||||
pluginsNodeLinks = AppendIfNotNil(pluginsNodeLinks, root.FindById("recordedQueries")) // enterprise only
|
||||
|
||||
accessNodeLinks = AppendIfNotNil(accessNodeLinks, root.FindById("users"))
|
||||
if globalUsers := root.FindById("global-users"); globalUsers != nil {
|
||||
globalUsers.Text = "Users (All orgs)"
|
||||
accessNodeLinks = append(accessNodeLinks, globalUsers)
|
||||
}
|
||||
accessNodeLinks = AppendIfNotNil(accessNodeLinks, root.FindById("teams"))
|
||||
accessNodeLinks = AppendIfNotNil(accessNodeLinks, root.FindById("serviceaccounts"))
|
||||
accessNodeLinks = AppendIfNotNil(accessNodeLinks, root.FindById("apikeys"))
|
||||
accessNodeLinks = AppendIfNotNil(accessNodeLinks, root.FindById("plugin-page-grafana-auth-app")) // Cloud Access Policies
|
||||
|
||||
generalNode := &NavLink{
|
||||
Text: "General",
|
||||
Id: NavIDAdminGeneral,
|
||||
Url: "/admin/general",
|
||||
Icon: "shield",
|
||||
Children: generalNodeLinks,
|
||||
}
|
||||
|
||||
pluginsNode := &NavLink{
|
||||
Text: "Plugins and data",
|
||||
Id: NavIDAdminPlugins,
|
||||
Url: "/admin/plugins",
|
||||
Icon: "shield",
|
||||
Children: pluginsNodeLinks,
|
||||
}
|
||||
|
||||
accessNode := &NavLink{
|
||||
Text: "Users and access",
|
||||
Id: NavIDAdminAccess,
|
||||
Url: "/admin/access",
|
||||
Icon: "shield",
|
||||
Children: accessNodeLinks,
|
||||
}
|
||||
|
||||
adminNodeLinks := []*NavLink{}
|
||||
|
||||
if len(generalNode.Children) > 0 {
|
||||
adminNodeLinks = append(adminNodeLinks, generalNode)
|
||||
}
|
||||
|
||||
if len(pluginsNode.Children) > 0 {
|
||||
adminNodeLinks = append(adminNodeLinks, pluginsNode)
|
||||
}
|
||||
|
||||
if len(accessNode.Children) > 0 {
|
||||
adminNodeLinks = append(adminNodeLinks, accessNode)
|
||||
}
|
||||
|
||||
if len(adminNodeLinks) > 0 {
|
||||
orgAdminNode.Children = adminNodeLinks
|
||||
} else {
|
||||
root.RemoveSection(orgAdminNode)
|
||||
}
|
||||
}
|
||||
|
||||
if serverAdminNode := root.FindById(NavIDAdmin); serverAdminNode != nil {
|
||||
root.RemoveSection(serverAdminNode)
|
||||
}
|
||||
}
|
||||
|
||||
func AppendIfNotNil(children []*NavLink, newChild *NavLink) []*NavLink {
|
||||
if newChild != nil {
|
||||
return append(children, newChild)
|
||||
}
|
||||
|
||||
return children
|
||||
}
|
||||
|
||||
func FindById(nodes []*NavLink, id string) *NavLink {
|
||||
for _, child := range nodes {
|
||||
if child.Id == id {
|
||||
|
||||
@@ -33,18 +33,20 @@ func TestNavTreeRoot(t *testing.T) {
|
||||
require.Equal(t, 2, len(treeRoot.Children))
|
||||
})
|
||||
|
||||
t.Run("Should move admin section into cfg and rename when topnav is enabled", func(t *testing.T) {
|
||||
t.Run("Should create 3 new sections in the Admin node when topnav is enabled", func(t *testing.T) {
|
||||
treeRoot := NavTreeRoot{
|
||||
Children: []*NavLink{
|
||||
{Id: NavIDCfg},
|
||||
{Id: NavIDAdmin, Children: []*NavLink{{Id: "child"}}},
|
||||
{Id: NavIDAdmin, Children: []*NavLink{{Id: "upgrading"}, {Id: "plugins"}, {Id: "teams"}}},
|
||||
},
|
||||
}
|
||||
|
||||
treeRoot.RemoveEmptySectionsAndApplyNewInformationArchitecture(true)
|
||||
|
||||
require.Equal(t, "Administration", treeRoot.Children[0].Text)
|
||||
require.Equal(t, NavIDAdmin, treeRoot.Children[0].Children[0].Id)
|
||||
require.Equal(t, NavIDAdminGeneral, treeRoot.Children[0].Children[0].Id)
|
||||
require.Equal(t, NavIDAdminPlugins, treeRoot.Children[0].Children[1].Id)
|
||||
require.Equal(t, NavIDAdminAccess, treeRoot.Children[0].Children[2].Id)
|
||||
})
|
||||
|
||||
t.Run("Should move reports into Dashboards", func(t *testing.T) {
|
||||
|
||||
@@ -166,16 +166,8 @@ func (s *ServiceImpl) getServerAdminNode(c *models.ReqContext) *navtree.NavLink
|
||||
Children: adminNavLinks,
|
||||
}
|
||||
|
||||
if s.cfg.IsFeatureToggleEnabled(featuremgmt.FlagTopnav) {
|
||||
adminNode.SubTitle = "Manage server-wide settings and access to resources such as organizations, users, and licenses"
|
||||
}
|
||||
|
||||
if len(adminNavLinks) > 0 {
|
||||
if s.cfg.IsFeatureToggleEnabled(featuremgmt.FlagTopnav) {
|
||||
adminNode.Url = s.cfg.AppSubURL + "/admin/server"
|
||||
} else {
|
||||
adminNode.Url = adminNavLinks[0].Url
|
||||
}
|
||||
adminNode.Url = adminNavLinks[0].Url
|
||||
}
|
||||
|
||||
return adminNode
|
||||
|
||||
@@ -244,6 +244,7 @@ func (s *ServiceImpl) readNavigationSettings() {
|
||||
"grafana-incident-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 2, Text: "Incident"},
|
||||
"grafana-ml-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 3, Text: "Machine Learning"},
|
||||
"grafana-cloud-link-app": {SectionID: navtree.NavIDCfg},
|
||||
"grafana-auth-app": {SectionID: navtree.NavIDCfg},
|
||||
"grafana-easystart-app": {SectionID: navtree.NavIDRoot, SortWeight: navtree.WeightSavedItems + 1, Text: "Connections"},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user