The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/services/navtree/models.go

220 lines
6.0 KiB

package navtree
import (
"encoding/json"
"sort"
)
const (
// These weights may be used by an extension to reliably place
// itself in relation to a particular item in the menu. The weights
// are negative to ensure that the default items are placed above
// any items with default weight.
WeightHome = (iota - 20) * 100
WeightSavedItems
WeightDashboard
WeightExplore
WeightAlerting
WeightAlertsAndIncidents
WeightTestingAndSynthetics
WeightMonitoring
WeightCloudServiceProviders
WeightInfrastructure
WeightApplication
WeightFrontend
WeightAsserts
WeightDataConnections
WeightApps
WeightPlugin
WeightConfig
WeightProfile
WeightHelp
)
const (
NavIDRoot = "root"
NavIDDashboards = "dashboards/browse"
NavIDExplore = "explore"
NavIDCfg = "cfg" // NavIDCfg is the id for org configuration navigation node
NavIDAlertsAndIncidents = "alerts-and-incidents"
NavIDTestingAndSynthetics = "testing-and-synthetics"
NavIDAlerting = "alerting"
NavIDMonitoring = "monitoring"
NavIDInfrastructure = "infrastructure"
NavIDFrontend = "frontend"
NavIDReporting = "reports"
NavIDApps = "apps"
NavIDCfgGeneral = "cfg/general"
NavIDCfgPlugins = "cfg/plugins"
NavIDCfgAccess = "cfg/access"
)
type NavLink struct {
Id string `json:"id,omitempty"`
Text string `json:"text"`
SubTitle string `json:"subTitle,omitempty"`
Icon string `json:"icon,omitempty"` // Available icons can be browsed in Storybook: https://developers.grafana.com/ui/latest/index.html?path=/story/docs-overview-icon--icons-overview
Img string `json:"img,omitempty"`
Url string `json:"url,omitempty"`
Target string `json:"target,omitempty"`
SortWeight int64 `json:"sortWeight,omitempty"`
HideFromTabs bool `json:"hideFromTabs,omitempty"`
RoundIcon bool `json:"roundIcon,omitempty"`
IsSection bool `json:"isSection,omitempty"`
Children []*NavLink `json:"children,omitempty"`
HighlightText string `json:"highlightText,omitempty"`
HighlightID string `json:"highlightId,omitempty"`
EmptyMessageId string `json:"emptyMessageId,omitempty"`
PluginID string `json:"pluginId,omitempty"` // (Optional) The ID of the plugin that registered nav link (e.g. as a standalone plugin page)
IsCreateAction bool `json:"isCreateAction,omitempty"`
Keywords []string `json:"keywords,omitempty"`
}
func (node *NavLink) Sort() {
Sort(node.Children)
}
type NavTreeRoot struct {
Children []*NavLink
}
func (root *NavTreeRoot) AddSection(node *NavLink) {
root.Children = append(root.Children, node)
}
func (root *NavTreeRoot) RemoveSection(node *NavLink) {
var result []*NavLink
for _, child := range root.Children {
if child != node {
result = append(result, child)
}
}
root.Children = result
}
func (root *NavTreeRoot) FindById(id string) *NavLink {
return FindById(root.Children, id)
}
func (root *NavTreeRoot) FindByURL(url string) *NavLink {
return FindByURL(root.Children, url)
}
func (root *NavTreeRoot) Sort() {
Sort(root.Children)
}
func (root *NavTreeRoot) MarshalJSON() ([]byte, error) {
return json.Marshal(root.Children)
}
func Sort(nodes []*NavLink) {
sort.SliceStable(nodes, func(i, j int) bool {
iw := nodes[i].SortWeight
if iw == 0 {
iw = int64(i) + 1
}
jw := nodes[j].SortWeight
if jw == 0 {
jw = int64(j) + 1
}
return iw < jw
})
for _, child := range nodes {
child.Sort()
}
}
func (root *NavTreeRoot) ApplyHelpVersion(version string) {
helpNode := root.FindById("help")
if helpNode != nil {
helpNode.SubTitle = version
}
}
func (root *NavTreeRoot) ApplyCostManagementIA() {
orgAdminNode := root.FindById(NavIDCfg)
var costManagementApp *NavLink
var adaptiveMetricsApp *NavLink
var attributionsApp *NavLink
var logVolumeExplorerApp *NavLink
if orgAdminNode != nil {
adminNodeLinks := []*NavLink{}
for _, element := range orgAdminNode.Children {
switch navId := element.Id; navId {
case "plugin-page-grafana-costmanagementui-app":
costManagementApp = element
case "plugin-page-grafana-adaptive-metrics-app":
adaptiveMetricsApp = element
case "plugin-page-grafana-attributions-app":
attributionsApp = element
case "plugin-page-grafana-logvolumeexplorer-app":
logVolumeExplorerApp = element
default:
adminNodeLinks = append(adminNodeLinks, element)
}
}
if costManagementApp != nil {
costManagementMetricsNode := FindByURL(costManagementApp.Children, "/a/grafana-costmanagementui-app/metrics")
if costManagementMetricsNode != nil {
if adaptiveMetricsApp != nil {
costManagementMetricsNode.Children = append(costManagementMetricsNode.Children, adaptiveMetricsApp)
}
if attributionsApp != nil {
costManagementMetricsNode.Children = append(costManagementMetricsNode.Children, attributionsApp)
}
}
costManagementLogsNode := FindByURL(costManagementApp.Children, "/a/grafana-costmanagementui-app/logs")
if costManagementLogsNode != nil {
if logVolumeExplorerApp != nil {
costManagementLogsNode.Children = append(costManagementLogsNode.Children, logVolumeExplorerApp)
}
}
adminNodeLinks = append(adminNodeLinks, costManagementApp)
}
orgAdminNode.Children = adminNodeLinks
}
}
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 {
return child
} else if len(child.Children) > 0 {
if found := FindById(child.Children, id); found != nil {
return found
}
}
}
return nil
}
func FindByURL(nodes []*NavLink, url string) *NavLink {
for _, child := range nodes {
if child.Url == url {
return child
} else if len(child.Children) > 0 {
if found := FindByURL(child.Children, url); found != nil {
return found
}
}
}
return nil
}