2022-09-23 04:04:48 +08:00
package navtreeimpl
import (
"fmt"
"sort"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"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/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/navtree"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsettings"
pref "github.com/grafana/grafana/pkg/services/preference"
2022-10-08 02:31:45 +08:00
"github.com/grafana/grafana/pkg/services/querylibrary"
2022-09-23 04:04:48 +08:00
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/setting"
)
type ServiceImpl struct {
cfg * setting . Cfg
log log . Logger
accessControl ac . AccessControl
pluginStore plugins . Store
pluginSettings pluginsettings . Service
starService star . Service
features * featuremgmt . FeatureManager
dashboardService dashboards . DashboardService
accesscontrolService ac . Service
kvStore kvstore . KVStore
apiKeyService apikey . Service
2022-10-08 02:31:45 +08:00
queryLibraryService querylibrary . HTTPService
2022-09-28 14:29:35 +08:00
// Navigation
navigationAppConfig map [ string ] NavigationAppConfig
navigationAppPathConfig map [ string ] NavigationAppConfig
}
type NavigationAppConfig struct {
SectionID string
SortWeight int64
2022-09-23 04:04:48 +08:00
}
2022-10-08 02:31:45 +08:00
func ProvideService ( cfg * setting . Cfg , accessControl ac . AccessControl , pluginStore plugins . Store , pluginSettings pluginsettings . Service , starService star . Service , features * featuremgmt . FeatureManager , dashboardService dashboards . DashboardService , accesscontrolService ac . Service , kvStore kvstore . KVStore , apiKeyService apikey . Service , queryLibraryService querylibrary . HTTPService ) navtree . Service {
2022-09-28 14:29:35 +08:00
service := & ServiceImpl {
2022-09-23 04:04:48 +08:00
cfg : cfg ,
log : log . New ( "navtree service" ) ,
accessControl : accessControl ,
pluginStore : pluginStore ,
pluginSettings : pluginSettings ,
starService : starService ,
features : features ,
dashboardService : dashboardService ,
accesscontrolService : accesscontrolService ,
kvStore : kvStore ,
apiKeyService : apiKeyService ,
2022-10-08 02:31:45 +08:00
queryLibraryService : queryLibraryService ,
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
service . readNavigationSettings ( )
return service
2022-09-23 04:04:48 +08:00
}
//nolint:gocyclo
2022-09-28 14:29:35 +08:00
func ( s * ServiceImpl ) GetNavTree ( c * models . ReqContext , hasEditPerm bool , prefs * pref . Preference ) ( * navtree . NavTreeRoot , error ) {
2022-09-23 04:04:48 +08:00
hasAccess := ac . HasAccess ( s . accessControl , c )
2022-09-28 14:29:35 +08:00
treeRoot := & navtree . NavTreeRoot { }
2022-09-23 04:04:48 +08:00
2022-10-03 22:05:19 +08:00
if s . features . IsEnabled ( featuremgmt . FlagTopnav ) {
treeRoot . AddSection ( s . getHomeNode ( c , prefs ) )
}
2022-09-23 04:04:48 +08:00
if hasAccess ( ac . ReqSignedIn , ac . EvalPermission ( dashboards . ActionDashboardsRead ) ) {
2022-10-03 22:05:19 +08:00
starredItemsLinks , err := s . buildStarredItemsNavLinks ( c )
2022-09-23 04:04:48 +08:00
if err != nil {
return nil , err
}
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( & navtree . NavLink {
2022-09-23 04:04:48 +08:00
Text : "Starred" ,
Id : "starred" ,
Icon : "star" ,
SortWeight : navtree . WeightSavedItems ,
Section : navtree . NavSectionCore ,
Children : starredItemsLinks ,
EmptyMessageId : "starred-empty" ,
} )
dashboardChildLinks := s . buildDashboardNavLinks ( c , hasEditPerm )
dashboardLink := & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Dashboards" ,
Id : navtree . NavIDDashboards ,
SubTitle : "Create and manage dashboards to visualize your data" ,
Icon : "apps" ,
Url : s . cfg . AppSubURL + "/dashboards" ,
SortWeight : navtree . WeightDashboard ,
Section : navtree . NavSectionCore ,
Children : dashboardChildLinks ,
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( dashboardLink )
2022-09-23 04:04:48 +08:00
}
canExplore := func ( context * models . ReqContext ) bool {
return c . OrgRole == org . RoleAdmin || c . OrgRole == org . RoleEditor || setting . ViewersCanEdit
}
if setting . ExploreEnabled && hasAccess ( canExplore , ac . EvalPermission ( ac . ActionDatasourcesExplore ) ) {
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( & navtree . NavLink {
2022-09-23 04:04:48 +08:00
Text : "Explore" ,
Id : "explore" ,
SubTitle : "Explore your data" ,
Icon : "compass" ,
SortWeight : navtree . WeightExplore ,
Section : navtree . NavSectionCore ,
Url : s . cfg . AppSubURL + "/explore" ,
} )
}
2022-10-08 02:31:45 +08:00
if ! s . queryLibraryService . IsDisabled ( ) {
treeRoot . AddSection ( & navtree . NavLink {
Text : "Query Library" ,
Id : "query" ,
SubTitle : "Store, import, export and manage your team queries in an easy way." ,
Icon : "file-search-alt" ,
SortWeight : navtree . WeightQueryLibrary ,
Section : navtree . NavSectionCore ,
Url : s . cfg . AppSubURL + "/query-library" ,
} )
}
2022-09-28 14:29:35 +08:00
if setting . ProfileEnabled && c . IsSignedIn {
treeRoot . AddSection ( s . getProfileNode ( c ) )
}
2022-09-23 04:04:48 +08:00
_ , uaIsDisabledForOrg := s . cfg . UnifiedAlerting . DisabledOrgs [ c . OrgID ]
uaVisibleForOrg := s . cfg . UnifiedAlerting . IsEnabled ( ) && ! uaIsDisabledForOrg
if setting . AlertingEnabled != nil && * setting . AlertingEnabled {
2022-09-28 14:29:35 +08:00
if legacyAlertSection := s . buildLegacyAlertNavLinks ( c ) ; legacyAlertSection != nil {
treeRoot . AddSection ( legacyAlertSection )
}
2022-09-23 04:04:48 +08:00
} else if uaVisibleForOrg {
2022-09-28 14:29:35 +08:00
if alertingSection := s . buildAlertNavLinks ( c , hasEditPerm ) ; alertingSection != nil {
treeRoot . AddSection ( alertingSection )
}
2022-09-23 04:04:48 +08:00
}
if s . features . IsEnabled ( featuremgmt . FlagDataConnectionsConsole ) {
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( s . buildDataConnectionsNavLink ( c ) )
2022-09-23 04:04:48 +08:00
}
if s . features . IsEnabled ( featuremgmt . FlagLivePipeline ) {
liveNavLinks := [ ] * navtree . NavLink { }
liveNavLinks = append ( liveNavLinks , & navtree . NavLink {
Text : "Status" , Id : "live-status" , Url : s . cfg . AppSubURL + "/live" , Icon : "exchange-alt" ,
} )
liveNavLinks = append ( liveNavLinks , & navtree . NavLink {
Text : "Pipeline" , Id : "live-pipeline" , Url : s . cfg . AppSubURL + "/live/pipeline" , Icon : "arrow-to-right" ,
} )
liveNavLinks = append ( liveNavLinks , & navtree . NavLink {
Text : "Cloud" , Id : "live-cloud" , Url : s . cfg . AppSubURL + "/live/cloud" , Icon : "cloud-upload" ,
} )
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( & navtree . NavLink {
2022-09-23 04:04:48 +08:00
Id : "live" ,
Text : "Live" ,
SubTitle : "Event streaming" ,
Icon : "exchange-alt" ,
Url : s . cfg . AppSubURL + "/live" ,
Children : liveNavLinks ,
Section : navtree . NavSectionConfig ,
HideFromTabs : true ,
} )
}
2022-09-28 14:29:35 +08:00
orgAdminNode , err := s . getOrgAdminNode ( c )
2022-09-23 04:04:48 +08:00
2022-09-28 14:29:35 +08:00
if orgAdminNode != nil {
treeRoot . AddSection ( orgAdminNode )
} else if err != nil {
return nil , err
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
serverAdminNode := s . getServerAdminNode ( c )
2022-09-23 04:04:48 +08:00
2022-09-28 14:29:35 +08:00
if serverAdminNode != nil {
treeRoot . AddSection ( serverAdminNode )
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
s . addHelpLinks ( treeRoot , c )
2022-09-23 04:04:48 +08:00
2022-09-28 14:29:35 +08:00
if err := s . addAppLinks ( treeRoot , c ) ; err != nil {
return nil , err
}
2022-09-23 04:04:48 +08:00
2022-09-28 14:29:35 +08:00
return treeRoot , nil
2022-09-23 04:04:48 +08:00
}
2022-10-03 22:05:19 +08:00
func ( s * ServiceImpl ) getHomeNode ( c * models . ReqContext , prefs * pref . Preference ) * navtree . NavLink {
homeUrl := s . cfg . AppSubURL + "/"
homePage := s . cfg . HomePage
if prefs . HomeDashboardID == 0 && len ( homePage ) > 0 {
homeUrl = homePage
}
if prefs . HomeDashboardID != 0 {
slugQuery := models . GetDashboardRefByIdQuery { Id : prefs . HomeDashboardID }
err := s . dashboardService . GetDashboardUIDById ( c . Req . Context ( ) , & slugQuery )
if err == nil {
homeUrl = models . GetDashboardUrl ( slugQuery . Result . Uid , slugQuery . Result . Slug )
}
}
return & navtree . NavLink {
Text : "Home" ,
Id : "home" ,
Url : homeUrl ,
Icon : "home-alt" ,
Section : navtree . NavSectionCore ,
SortWeight : navtree . WeightHome ,
}
}
2022-09-28 14:29:35 +08:00
func ( s * ServiceImpl ) addHelpLinks ( treeRoot * navtree . NavTreeRoot , c * models . ReqContext ) {
2022-09-23 04:04:48 +08:00
if setting . HelpEnabled {
helpVersion := fmt . Sprintf ( ` %s v%s (%s) ` , setting . ApplicationName , setting . BuildVersion , setting . BuildCommit )
if s . cfg . AnonymousHideVersion && ! c . IsSignedIn {
helpVersion = setting . ApplicationName
}
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( & navtree . NavLink {
2022-09-23 04:04:48 +08:00
Text : "Help" ,
SubTitle : helpVersion ,
Id : "help" ,
Url : "#" ,
Icon : "question-circle" ,
SortWeight : navtree . WeightHelp ,
Section : navtree . NavSectionConfig ,
Children : [ ] * navtree . NavLink { } ,
} )
}
}
func ( s * ServiceImpl ) getProfileNode ( c * models . ReqContext ) * navtree . NavLink {
// Only set login if it's different from the name
var login string
if c . SignedInUser . Login != c . SignedInUser . NameOrFallback ( ) {
login = c . SignedInUser . Login
}
gravatarURL := dtos . GetGravatarUrl ( c . Email )
children := [ ] * navtree . NavLink {
{
Text : "Preferences" , Id : "profile/settings" , Url : s . cfg . AppSubURL + "/profile" , Icon : "sliders-v-alt" ,
} ,
}
children = append ( children , & navtree . NavLink {
Text : "Notification history" , Id : "profile/notifications" , Url : s . cfg . AppSubURL + "/profile/notifications" , Icon : "bell" ,
} )
if setting . AddChangePasswordLink ( ) {
children = append ( children , & navtree . NavLink {
Text : "Change password" , Id : "profile/password" , Url : s . cfg . AppSubURL + "/profile/password" ,
Icon : "lock" ,
} )
}
if ! setting . DisableSignoutMenu {
// add sign out first
children = append ( children , & navtree . NavLink {
Text : "Sign out" ,
Id : "sign-out" ,
Url : s . cfg . AppSubURL + "/logout" ,
Icon : "arrow-from-right" ,
Target : "_self" ,
HideFromTabs : true ,
} )
}
return & navtree . NavLink {
Text : c . SignedInUser . NameOrFallback ( ) ,
SubTitle : login ,
Id : "profile" ,
Img : gravatarURL ,
Url : s . cfg . AppSubURL + "/profile" ,
Section : navtree . NavSectionConfig ,
SortWeight : navtree . WeightProfile ,
Children : children ,
RoundIcon : true ,
}
}
2022-10-03 22:05:19 +08:00
func ( s * ServiceImpl ) buildStarredItemsNavLinks ( c * models . ReqContext ) ( [ ] * navtree . NavLink , error ) {
2022-09-23 04:04:48 +08:00
starredItemsChildNavs := [ ] * navtree . NavLink { }
query := star . GetUserStarsQuery {
UserID : c . SignedInUser . UserID ,
}
starredDashboardResult , err := s . starService . GetByUser ( c . Req . Context ( ) , & query )
if err != nil {
return nil , err
}
starredDashboards := [ ] * models . Dashboard { }
starredDashboardsCounter := 0
for dashboardId := range starredDashboardResult . UserStars {
// Set a loose limit to the first 50 starred dashboards found
if starredDashboardsCounter > 50 {
break
}
starredDashboardsCounter ++
query := & models . GetDashboardQuery {
Id : dashboardId ,
OrgId : c . OrgID ,
}
err := s . dashboardService . GetDashboard ( c . Req . Context ( ) , query )
if err == nil {
starredDashboards = append ( starredDashboards , query . Result )
}
}
if len ( starredDashboards ) > 0 {
sort . Slice ( starredDashboards , func ( i , j int ) bool {
return starredDashboards [ i ] . Title < starredDashboards [ j ] . Title
} )
for _ , starredItem := range starredDashboards {
starredItemsChildNavs = append ( starredItemsChildNavs , & navtree . NavLink {
Id : starredItem . Uid ,
Text : starredItem . Title ,
Url : starredItem . GetUrl ( ) ,
} )
}
}
return starredItemsChildNavs , nil
}
func ( s * ServiceImpl ) buildDashboardNavLinks ( c * models . ReqContext , hasEditPerm bool ) [ ] * navtree . NavLink {
hasAccess := ac . HasAccess ( s . accessControl , c )
hasEditPermInAnyFolder := func ( c * models . ReqContext ) bool {
return hasEditPerm
}
dashboardChildNavs := [ ] * navtree . NavLink { }
2022-09-28 14:29:35 +08:00
2022-09-23 04:04:48 +08:00
if ! s . features . IsEnabled ( featuremgmt . FlagTopnav ) {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2022-09-28 14:29:35 +08:00
Text : "Browse" , Id : navtree . NavIDDashboardsBrowse , Url : s . cfg . AppSubURL + "/dashboards" , Icon : "sitemap" ,
2022-09-23 04:04:48 +08:00
} )
}
2022-09-28 14:29:35 +08:00
2022-09-23 04:04:48 +08:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Playlists" , SubTitle : "Groups of dashboards that are displayed in a sequence" , Id : "dashboards/playlists" , Url : s . cfg . AppSubURL + "/playlists" , Icon : "presentation-play" ,
2022-09-23 04:04:48 +08:00
} )
if c . IsSignedIn {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Snapshots" ,
SubTitle : "Interactive, publically available, point-in-time representations of dashboards" ,
Id : "dashboards/snapshots" ,
Url : s . cfg . AppSubURL + "/dashboard/snapshots" ,
Icon : "camera" ,
2022-09-23 04:04:48 +08:00
} )
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Library panels" ,
SubTitle : "Reusable panels that can be added to multiple dashboards" ,
Id : "dashboards/library-panels" ,
Url : s . cfg . AppSubURL + "/library-panels" ,
Icon : "library-panel" ,
2022-09-23 04:04:48 +08:00
} )
}
if s . features . IsEnabled ( featuremgmt . FlagScenes ) {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "Scenes" ,
Id : "scenes" ,
Url : s . cfg . AppSubURL + "/scenes" ,
Icon : "apps" ,
} )
}
2022-09-28 14:29:35 +08:00
if hasEditPerm && ! s . features . IsEnabled ( featuremgmt . FlagTopnav ) {
2022-09-23 04:04:48 +08:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "Divider" , Divider : true , Id : "divider" , HideFromTabs : true ,
} )
if hasAccess ( hasEditPermInAnyFolder , ac . EvalPermission ( dashboards . ActionDashboardsCreate ) ) {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "New dashboard" , Icon : "plus" , Url : s . cfg . AppSubURL + "/dashboard/new" , HideFromTabs : true , Id : "dashboards/new" , ShowIconInNavbar : true ,
} )
}
if hasAccess ( ac . ReqOrgAdminOrEditor , ac . EvalPermission ( dashboards . ActionFoldersCreate ) ) {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "New folder" , SubTitle : "Create a new folder to organize your dashboards" , Id : "dashboards/folder/new" ,
Icon : "plus" , Url : s . cfg . AppSubURL + "/dashboards/folder/new" , HideFromTabs : true , ShowIconInNavbar : true ,
} )
}
if hasAccess ( hasEditPermInAnyFolder , ac . EvalPermission ( dashboards . ActionDashboardsCreate ) ) {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "Import" , SubTitle : "Import dashboard from file or Grafana.com" , Id : "dashboards/import" , Icon : "plus" ,
Url : s . cfg . AppSubURL + "/dashboard/import" , HideFromTabs : true , ShowIconInNavbar : true ,
} )
}
}
2022-09-28 14:29:35 +08:00
2022-09-23 04:04:48 +08:00
return dashboardChildNavs
}
2022-09-28 14:29:35 +08:00
func ( s * ServiceImpl ) buildLegacyAlertNavLinks ( c * models . ReqContext ) * navtree . NavLink {
2022-09-23 04:04:48 +08:00
var alertChildNavs [ ] * navtree . NavLink
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
Text : "Alert rules" , Id : "alert-list" , Url : s . cfg . AppSubURL + "/alerting/list" , Icon : "list-ul" ,
} )
if c . HasRole ( org . RoleEditor ) {
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
Text : "Notification channels" , Id : "channels" , Url : s . cfg . AppSubURL + "/alerting/notifications" ,
Icon : "comment-alt-share" ,
} )
}
var alertNav = navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Alerting" ,
SubTitle : "Learn about problems in your systems moments after they occur" ,
Id : "alerting-legacy" ,
Icon : "bell" ,
Children : alertChildNavs ,
Section : navtree . NavSectionCore ,
SortWeight : navtree . WeightAlerting ,
2022-09-23 04:04:48 +08:00
}
if s . features . IsEnabled ( featuremgmt . FlagTopnav ) {
alertNav . Url = s . cfg . AppSubURL + "/alerting"
} else {
alertNav . Url = s . cfg . AppSubURL + "/alerting/list"
}
2022-09-28 14:29:35 +08:00
return & alertNav
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
func ( s * ServiceImpl ) buildAlertNavLinks ( c * models . ReqContext , hasEditPerm bool ) * navtree . NavLink {
2022-09-23 04:04:48 +08:00
hasAccess := ac . HasAccess ( s . accessControl , c )
var alertChildNavs [ ] * navtree . NavLink
if hasAccess ( ac . ReqViewer , ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingRuleRead ) , ac . EvalPermission ( ac . ActionAlertingRuleExternalRead ) ) ) {
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Alert rules" , SubTitle : "Rules that determine whether an alert will fire" , Id : "alert-list" , Url : s . cfg . AppSubURL + "/alerting/list" , Icon : "list-ul" ,
2022-09-23 04:04:48 +08:00
} )
}
if hasAccess ( ac . ReqOrgAdminOrEditor , ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingNotificationsRead ) , ac . EvalPermission ( ac . ActionAlertingNotificationsExternalRead ) ) ) {
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Contact points" , SubTitle : "Decide how your contacts are notified when an alert fires" , Id : "receivers" , Url : s . cfg . AppSubURL + "/alerting/notifications" ,
Icon : "comment-alt-share" ,
2022-09-23 04:04:48 +08:00
} )
2022-10-03 17:09:32 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink { Text : "Notification policies" , SubTitle : "Determine how alerts are routed to contact points" , Id : "am-routes" , Url : s . cfg . AppSubURL + "/alerting/routes" , Icon : "sitemap" } )
2022-09-23 04:04:48 +08:00
}
if hasAccess ( ac . ReqViewer , ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingInstanceRead ) , ac . EvalPermission ( ac . ActionAlertingInstancesExternalRead ) ) ) {
2022-10-03 17:09:32 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink { Text : "Silences" , SubTitle : "Stop notifications from one or more alerting rules" , Id : "silences" , Url : s . cfg . AppSubURL + "/alerting/silences" , Icon : "bell-slash" } )
alertChildNavs = append ( alertChildNavs , & navtree . NavLink { Text : "Alert groups" , SubTitle : "See grouped alerts from an Alertmanager instance" , Id : "groups" , Url : s . cfg . AppSubURL + "/alerting/groups" , Icon : "layer-group" } )
2022-09-23 04:04:48 +08:00
}
if c . OrgRole == org . RoleAdmin {
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
Text : "Admin" , Id : "alerting-admin" , Url : s . cfg . AppSubURL + "/alerting/admin" ,
Icon : "cog" ,
} )
}
fallbackHasEditPerm := func ( * models . ReqContext ) bool { return hasEditPerm }
if hasAccess ( fallbackHasEditPerm , ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingRuleCreate ) , ac . EvalPermission ( ac . ActionAlertingRuleExternalWrite ) ) ) {
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
Text : "Divider" , Divider : true , Id : "divider" , HideFromTabs : true ,
} )
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
Text : "New alert rule" , SubTitle : "Create an alert rule" , Id : "alert" ,
Icon : "plus" , Url : s . cfg . AppSubURL + "/alerting/new" , HideFromTabs : true , ShowIconInNavbar : true ,
} )
}
if len ( alertChildNavs ) > 0 {
var alertNav = navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Alerting" ,
SubTitle : "Learn about problems in your systems moments after they occur" ,
Id : navtree . NavIDAlerting ,
Icon : "bell" ,
Children : alertChildNavs ,
Section : navtree . NavSectionCore ,
SortWeight : navtree . WeightAlerting ,
2022-09-23 04:04:48 +08:00
}
if s . features . IsEnabled ( featuremgmt . FlagTopnav ) {
alertNav . Url = s . cfg . AppSubURL + "/alerting"
} else {
alertNav . Url = s . cfg . AppSubURL + "/alerting/list"
}
2022-09-28 14:29:35 +08:00
return & alertNav
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
2022-09-23 04:04:48 +08:00
return nil
}
func ( s * ServiceImpl ) buildDataConnectionsNavLink ( c * models . ReqContext ) * navtree . NavLink {
var children [ ] * navtree . NavLink
var navLink * navtree . NavLink
2022-10-05 15:56:58 +08:00
baseId := "connections"
2022-09-23 04:04:48 +08:00
baseUrl := s . cfg . AppSubURL + "/" + baseId
children = append ( children , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Id : baseId + "-datasources" ,
Text : "Data sources" ,
Icon : "database" ,
SubTitle : "Add and configure data sources" ,
Url : baseUrl + "/datasources" ,
2022-09-23 04:04:48 +08:00
} )
children = append ( children , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Id : baseId + "-plugins" ,
Text : "Plugins" ,
Icon : "plug" ,
SubTitle : "Manage plugins" ,
Url : baseUrl + "/plugins" ,
2022-09-23 04:04:48 +08:00
} )
children = append ( children , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Id : baseId + "-cloud-integrations" ,
Text : "Cloud integrations" ,
Icon : "bolt" ,
SubTitle : "Manage your cloud integrations" ,
Url : baseUrl + "/cloud-integrations" ,
2022-09-23 04:04:48 +08:00
} )
navLink = & navtree . NavLink {
2022-10-05 15:56:58 +08:00
Text : "Connections" ,
2022-09-23 04:04:48 +08:00
Icon : "link" ,
Id : baseId ,
Url : baseUrl ,
Children : children ,
Section : navtree . NavSectionCore ,
SortWeight : navtree . WeightDataConnections ,
}
return navLink
}