From b727bd1c8d86143aeac8fd2addc80ff21217f2fe Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Tue, 20 May 2025 16:24:21 +0100 Subject: [PATCH] Chore: Move ml app to root (#105677) * move ml app to root * update translation * translate subtitle as well * fix casing --- pkg/services/navtree/navtreeimpl/applinks.go | 2 +- pkg/services/navtree/navtreeimpl/navtree.go | 80 ------------------- .../app/core/utils/navBarItem-translations.ts | 4 +- public/locales/en-US/grafana.json | 3 +- 4 files changed, 6 insertions(+), 83 deletions(-) diff --git a/pkg/services/navtree/navtreeimpl/applinks.go b/pkg/services/navtree/navtreeimpl/applinks.go index 50d5bb39c9c..66e656ac262 100644 --- a/pkg/services/navtree/navtreeimpl/applinks.go +++ b/pkg/services/navtree/navtreeimpl/applinks.go @@ -317,7 +317,7 @@ func (s *ServiceImpl) readNavigationSettings() { "grafana-irm-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 3, Text: "IRM"}, "grafana-oncall-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 4, Text: "OnCall"}, "grafana-incident-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 5, Text: "Incident"}, - "grafana-ml-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 6, Text: "Machine Learning"}, + "grafana-ml-app": {SectionID: navtree.NavIDRoot, SortWeight: navtree.WeightAIAndML, Text: "AI & machine learning", SubTitle: "Explore AI and machine learning features", Icon: "gf-ml-alt"}, "grafana-slo-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 7}, "grafana-cloud-link-app": {SectionID: navtree.NavIDCfgPlugins, SortWeight: 3}, "grafana-costmanagementui-app": {SectionID: navtree.NavIDCfg, Text: "Cost management"}, diff --git a/pkg/services/navtree/navtreeimpl/navtree.go b/pkg/services/navtree/navtreeimpl/navtree.go index 0a1682b026c..fdc345a8026 100644 --- a/pkg/services/navtree/navtreeimpl/navtree.go +++ b/pkg/services/navtree/navtreeimpl/navtree.go @@ -7,7 +7,6 @@ import ( "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/plugins" ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/authn" @@ -18,7 +17,6 @@ import ( "github.com/grafana/grafana/pkg/services/licensing" "github.com/grafana/grafana/pkg/services/navtree" "github.com/grafana/grafana/pkg/services/org" - pc "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" pref "github.com/grafana/grafana/pkg/services/preference" @@ -163,10 +161,6 @@ func (s *ServiceImpl) GetNavTree(c *contextmodel.ReqContext, prefs *pref.Prefere if alertingSection := s.buildAlertNavLinks(c); alertingSection != nil { treeRoot.AddSection(alertingSection) } - - if aimlSection := s.buildAIMLNavLinks(c); aimlSection != nil { - treeRoot.AddSection(aimlSection) - } } if connectionsSection := s.buildDataConnectionsNavLink(c); connectionsSection != nil { @@ -422,80 +416,6 @@ func (s *ServiceImpl) buildDashboardNavLinks(c *contextmodel.ReqContext) []*navt return dashboardChildNavs } -func (s *ServiceImpl) buildAIMLNavLinks(c *contextmodel.ReqContext) *navtree.NavLink { - hasAccess := ac.HasAccess(s.accessControl, c) - - pss, err := s.pluginSettings.GetPluginSettings(c.Req.Context(), &pluginsettings.GetArgs{OrgID: c.GetOrgID()}) - if err != nil { - s.log.Error("Failed to get plugin settings", "error", err) - return nil - } - - // Check if ML plugin is enabled - isMLPluginEnabled := false - for _, plugin := range s.pluginStore.Plugins(c.Req.Context(), plugins.TypeApp) { - if plugin.ID == "grafana-ml-app" { - // Check if plugin is enabled in settings - if plugin.AutoEnabled { - isMLPluginEnabled = true - break - } - for _, ps := range pss { - if ps.PluginID == plugin.ID && ps.Enabled { - isMLPluginEnabled = true - break - } - } - break - } - } - - // Return nil if plugin is not enabled - if !isMLPluginEnabled { - return nil - } - - // Check if user has access to the plugin - if !hasAccess(ac.EvalPermission(pc.ActionAppAccess, "grafana-ml-app")) { - return nil - } - - var aimlChildNavs []*navtree.NavLink - - aimlChildNavs = append(aimlChildNavs, &navtree.NavLink{ - Text: "Metric forecasting", - SubTitle: "Create a forecast", - Id: "ai-ml-metric-forecast", - Url: s.cfg.AppSubURL + "/a/grafana-ml-app/metric-forecast", - }) - - aimlChildNavs = append(aimlChildNavs, &navtree.NavLink{ - Text: "Outlier detection", - SubTitle: "Create an outlier detector", - Id: "ai-ml-outlier-detection", - Url: s.cfg.AppSubURL + "/a/grafana-ml-app/outlier-detector", - }) - - aimlChildNavs = append(aimlChildNavs, &navtree.NavLink{ - Text: "Sift investigations", - SubTitle: "View and create investigations", - Id: "ai-ml-sift-investigations", - Url: s.cfg.AppSubURL + "/a/grafana-ml-app/investigations", - }) - - var aimlNav = navtree.NavLink{ - Text: "AI & Machine Learning", - SubTitle: "Explore AI and machine learning features", - Id: "ai-ml-home", - Icon: "gf-ml-alt", - Children: aimlChildNavs, - SortWeight: navtree.WeightAIAndML, - Url: s.cfg.AppSubURL + "/a/grafana-ml-app/home", - } - - return &aimlNav -} - func (s *ServiceImpl) buildAlertNavLinks(c *contextmodel.ReqContext) *navtree.NavLink { hasAccess := ac.HasAccess(s.accessControl, c) var alertChildNavs []*navtree.NavLink diff --git a/public/app/core/utils/navBarItem-translations.ts b/public/app/core/utils/navBarItem-translations.ts index 0f48cf055d2..6c78e1de1e6 100644 --- a/public/app/core/utils/navBarItem-translations.ts +++ b/public/app/core/utils/navBarItem-translations.ts @@ -152,7 +152,7 @@ export function getNavTitle(navId: string | undefined) { case 'plugin-page-grafana-incident-app': return t('nav.incidents.title', 'Incident'); case 'plugin-page-grafana-ml-app': - return t('nav.machine-learning.title', 'Machine learning'); + return t('nav.machine-learning.title', 'AI & machine learning'); case 'plugin-page-grafana-slo-app': return t('nav.slo.title', 'SLO'); case 'plugin-page-k6-app': @@ -319,6 +319,8 @@ export function getNavSubTitle(navId: string | undefined) { 'nav.private-data-source-connections.subtitle', 'Query data that lives within a secured network without opening the network to inbound traffic from Grafana Cloud. Learn more in our docs.' ); + case 'plugin-page-grafana-ml-app': + return t('nav.machine-learning.subtitle', 'Explore AI and machine learning features'); default: return undefined; } diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index f74b6c9a05f..ed688e5c2d2 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -6776,7 +6776,8 @@ "title": "Library panels" }, "machine-learning": { - "title": "Machine learning" + "subtitle": "Explore AI and machine learning features", + "title": "AI & machine learning" }, "manage-folder": { "subtitle": "Manage folder dashboards and permissions"