func GetDataSourcePlugins(c *middleware.Context) { dsList := make(map[string]*plugins.DataSourcePlugin) if enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId); err != nil { c.JsonApiErr(500, "Failed to get org apps", err) return } else { for key, value := range enabledPlugins.DataSources { if !value.BuiltIn { dsList[key] = value } } c.JSON(200, dsList) } }
func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { settings, err := getFrontendSettingsMap(c) if err != nil { return nil, err } var data = dtos.IndexViewData{ User: &dtos.CurrentUser{ Id: c.UserId, IsSignedIn: c.IsSignedIn, Login: c.Login, Email: c.Email, Name: c.Name, LightTheme: c.Theme == "light", OrgId: c.OrgId, OrgName: c.OrgName, OrgRole: c.OrgRole, GravatarUrl: dtos.GetGravatarUrl(c.Email), IsGrafanaAdmin: c.IsGrafanaAdmin, }, Settings: settings, AppUrl: setting.AppUrl, AppSubUrl: setting.AppSubUrl, GoogleAnalyticsId: setting.GoogleAnalyticsId, GoogleTagManagerId: setting.GoogleTagManagerId, } if setting.DisableGravatar { data.User.GravatarUrl = setting.AppSubUrl + "/img/user_profile.png" } if len(data.User.Name) == 0 { data.User.Name = data.User.Login } themeUrlParam := c.Query("theme") if themeUrlParam == "light" { data.User.LightTheme = true } data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Dashboards", Icon: "fa fa-fw fa-th-large", Url: "/", }) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Playlists", Icon: "fa fa-fw fa-list", Url: "/playlists", }) if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", Icon: "fa fa-fw fa-database", Url: "/datasources", }) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Apps", Icon: "fa fa-fw fa-cubes", Url: "/apps", }) } enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId) if err != nil { return nil, err } for _, plugin := range enabledPlugins.Apps { if plugin.Module != "" { data.PluginModules = append(data.PluginModules, plugin.Module) } if plugin.Css != nil { data.PluginCss = append(data.PluginCss, &dtos.PluginCss{Light: plugin.Css.Light, Dark: plugin.Css.Dark}) } if plugin.Pinned { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: plugin.Name, Url: "/apps/edit/" + plugin.Id, Img: plugin.Info.Logos.Small, }) } } return &data, nil }
func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { settings, err := getFrontendSettingsMap(c) if err != nil { return nil, err } prefsQuery := m.GetPreferencesWithDefaultsQuery{OrgId: c.OrgId, UserId: c.UserId} if err := bus.Dispatch(&prefsQuery); err != nil { return nil, err } prefs := prefsQuery.Result // Read locale from acccept-language acceptLang := c.Req.Header.Get("Accept-Language") locale := "en-US" if len(acceptLang) > 0 { parts := strings.Split(acceptLang, ",") locale = parts[0] } appUrl := setting.AppUrl appSubUrl := setting.AppSubUrl // special case when doing localhost call from phantomjs if c.IsRenderCall { appUrl = fmt.Sprintf("%s://localhost:%s", setting.Protocol, setting.HttpPort) appSubUrl = "" settings["appSubUrl"] = "" } var data = dtos.IndexViewData{ User: &dtos.CurrentUser{ Id: c.UserId, IsSignedIn: c.IsSignedIn, Login: c.Login, Email: c.Email, Name: c.Name, OrgId: c.OrgId, OrgName: c.OrgName, OrgRole: c.OrgRole, GravatarUrl: dtos.GetGravatarUrl(c.Email), IsGrafanaAdmin: c.IsGrafanaAdmin, LightTheme: prefs.Theme == "light", Timezone: prefs.Timezone, Locale: locale, HelpFlags1: c.HelpFlags1, }, Settings: settings, AppUrl: appUrl, AppSubUrl: appSubUrl, GoogleAnalyticsId: setting.GoogleAnalyticsId, GoogleTagManagerId: setting.GoogleTagManagerId, BuildVersion: setting.BuildVersion, BuildCommit: setting.BuildCommit, NewGrafanaVersion: plugins.GrafanaLatestVersion, NewGrafanaVersionExists: plugins.GrafanaHasUpdate, } if setting.DisableGravatar { data.User.GravatarUrl = setting.AppSubUrl + "/public/img/transparent.png" } if len(data.User.Name) == 0 { data.User.Name = data.User.Login } themeUrlParam := c.Query("theme") if themeUrlParam == "light" { data.User.LightTheme = true } dashboardChildNavs := []*dtos.NavLink{ {Text: "Home", Url: setting.AppSubUrl + "/"}, {Text: "Playlists", Url: setting.AppSubUrl + "/playlists"}, {Text: "Snapshots", Url: setting.AppSubUrl + "/dashboard/snapshots"}, } if c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR { dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Divider: true}) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "New", Icon: "fa fa-plus", Url: setting.AppSubUrl + "/dashboard/new"}) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "Import", Icon: "fa fa-download", Url: setting.AppSubUrl + "/dashboard/new/?editview=import"}) } data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Dashboards", Icon: "icon-gf icon-gf-dashboard", Url: setting.AppSubUrl + "/", Children: dashboardChildNavs, }) if c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR { alertChildNavs := []*dtos.NavLink{ {Text: "Alert List", Url: setting.AppSubUrl + "/alerting/list"}, {Text: "Notifications", Url: setting.AppSubUrl + "/alerting/notifications"}, } data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Alerting", Icon: "icon-gf icon-gf-alert", Url: setting.AppSubUrl + "/alerting/list", Children: alertChildNavs, }) } if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", Icon: "icon-gf icon-gf-datasources", Url: setting.AppSubUrl + "/datasources", }) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Plugins", Icon: "icon-gf icon-gf-apps", Url: setting.AppSubUrl + "/plugins", }) } enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId) if err != nil { return nil, err } for _, plugin := range enabledPlugins.Apps { if plugin.Pinned { appLink := &dtos.NavLink{ Text: plugin.Name, Url: plugin.DefaultNavUrl, Img: plugin.Info.Logos.Small, } for _, include := range plugin.Includes { if !c.HasUserRole(include.Role) { continue } if include.Type == "page" && include.AddToNav { link := &dtos.NavLink{ Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/page/" + include.Slug, Text: include.Name, } appLink.Children = append(appLink.Children, link) } if include.Type == "dashboard" && include.AddToNav { link := &dtos.NavLink{ Url: setting.AppSubUrl + "/dashboard/db/" + include.Slug, Text: include.Name, } appLink.Children = append(appLink.Children, link) } } if len(appLink.Children) > 0 && c.OrgRole == m.ROLE_ADMIN { appLink.Children = append(appLink.Children, &dtos.NavLink{Divider: true}) appLink.Children = append(appLink.Children, &dtos.NavLink{Text: "Plugin Config", Icon: "fa fa-cog", Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/edit"}) } if len(appLink.Children) > 0 { data.MainNavLinks = append(data.MainNavLinks, appLink) } } } if c.IsGrafanaAdmin { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Admin", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin", Children: []*dtos.NavLink{ {Text: "Global Users", Url: setting.AppSubUrl + "/admin/users"}, {Text: "Global Orgs", Url: setting.AppSubUrl + "/admin/orgs"}, {Text: "Server Settings", Url: setting.AppSubUrl + "/admin/settings"}, {Text: "Server Stats", Url: setting.AppSubUrl + "/admin/stats"}, }, }) } return &data, nil }
func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, error) { orgDataSources := make([]*m.DataSource, 0) if c.OrgId != 0 { query := m.GetDataSourcesQuery{OrgId: c.OrgId} err := bus.Dispatch(&query) if err != nil { return nil, err } orgDataSources = query.Result } datasources := make(map[string]interface{}) var defaultDatasource string enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId) if err != nil { return nil, err } for _, ds := range orgDataSources { url := ds.Url if ds.Access == m.DS_ACCESS_PROXY { url = "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10) } var dsMap = map[string]interface{}{ "type": ds.Type, "name": ds.Name, "url": url, } meta, exists := enabledPlugins.DataSources[ds.Type] if !exists { log.Error(3, "Could not find plugin definition for data source: %v", ds.Type) continue } dsMap["meta"] = meta if ds.IsDefault { defaultDatasource = ds.Name } if ds.JsonData != nil { dsMap["jsonData"] = ds.JsonData } if ds.Access == m.DS_ACCESS_DIRECT { if ds.BasicAuth { dsMap["basicAuth"] = util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword) } if ds.WithCredentials { dsMap["withCredentials"] = ds.WithCredentials } if ds.Type == m.DS_INFLUXDB_08 { dsMap["username"] = ds.User dsMap["password"] = ds.Password dsMap["url"] = url + "/db/" + ds.Database } if ds.Type == m.DS_INFLUXDB { dsMap["username"] = ds.User dsMap["password"] = ds.Password dsMap["database"] = ds.Database dsMap["url"] = url } } if ds.Type == m.DS_ES { dsMap["index"] = ds.Database } if ds.Type == m.DS_INFLUXDB { dsMap["database"] = ds.Database } if ds.Type == m.DS_PROMETHEUS { // add unproxied server URL for link to Prometheus web UI dsMap["directUrl"] = ds.Url } datasources[ds.Name] = dsMap } // add grafana backend data source grafanaDatasourceMeta, _ := plugins.DataSources["grafana"] datasources["-- Grafana --"] = map[string]interface{}{ "type": "grafana", "name": "-- Grafana --", "meta": grafanaDatasourceMeta, } // add mixed backend data source datasources["-- Mixed --"] = map[string]interface{}{ "type": "mixed", "meta": plugins.DataSources["mixed"], } if defaultDatasource == "" { defaultDatasource = "-- Grafana --" } panels := map[string]interface{}{} for _, panel := range enabledPlugins.Panels { panels[panel.Id] = map[string]interface{}{ "module": panel.Module, "baseUrl": panel.BaseUrl, "name": panel.Name, "id": panel.Id, "info": panel.Info, "hideFromList": panel.HideFromList, "sort": getPanelSort(panel.Id), } } jsonObj := map[string]interface{}{ "defaultDatasource": defaultDatasource, "datasources": datasources, "panels": panels, "appSubUrl": setting.AppSubUrl, "allowOrgCreate": (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin, "authProxyEnabled": setting.AuthProxyEnabled, "ldapEnabled": setting.LdapEnabled, "buildInfo": map[string]interface{}{ "version": setting.BuildVersion, "commit": setting.BuildCommit, "buildstamp": setting.BuildStamp, "latestVersion": plugins.GrafanaLatestVersion, "hasUpdate": plugins.GrafanaHasUpdate, "env": setting.Env, }, } return jsonObj, nil }
func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { settings, err := getFrontendSettingsMap(c) if err != nil { return nil, err } prefsQuery := m.GetPreferencesWithDefaultsQuery{OrgId: c.OrgId, UserId: c.UserId} if err := bus.Dispatch(&prefsQuery); err != nil { return nil, err } prefs := prefsQuery.Result var data = dtos.IndexViewData{ User: &dtos.CurrentUser{ Id: c.UserId, IsSignedIn: c.IsSignedIn, Login: c.Login, Email: c.Email, Name: c.Name, OrgId: c.OrgId, OrgName: c.OrgName, OrgRole: c.OrgRole, GravatarUrl: dtos.GetGravatarUrl(c.Email), IsGrafanaAdmin: c.IsGrafanaAdmin, LightTheme: prefs.Theme == "light", Timezone: prefs.Timezone, }, Settings: settings, AppUrl: setting.AppUrl, AppSubUrl: setting.AppSubUrl, GoogleAnalyticsId: setting.GoogleAnalyticsId, GoogleTagManagerId: setting.GoogleTagManagerId, } if setting.DisableGravatar { data.User.GravatarUrl = setting.AppSubUrl + "/public/img/transparent.png" } if len(data.User.Name) == 0 { data.User.Name = data.User.Login } themeUrlParam := c.Query("theme") if themeUrlParam == "light" { data.User.LightTheme = true } dashboardChildNavs := []*dtos.NavLink{ {Text: "Home", Url: setting.AppSubUrl + "/"}, {Text: "Playlists", Url: setting.AppSubUrl + "/playlists"}, {Text: "Snapshots", Url: setting.AppSubUrl + "/dashboard/snapshots"}, } if c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR { dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Divider: true}) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "New", Icon: "fa fa-plus", Url: setting.AppSubUrl + "/dashboard/new"}) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "Import", Icon: "fa fa-download", Url: setting.AppSubUrl + "/import/dashboard"}) } data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Dashboards", Icon: "icon-gf icon-gf-dashboard", Url: setting.AppSubUrl + "/", Children: dashboardChildNavs, }) if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", Icon: "icon-gf icon-gf-datasources", Url: setting.AppSubUrl + "/datasources", }) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Plugins", Icon: "icon-gf icon-gf-apps", Url: setting.AppSubUrl + "/plugins", }) } enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId) if err != nil { return nil, err } for _, plugin := range enabledPlugins.Apps { if plugin.Pinned { appLink := &dtos.NavLink{ Text: plugin.Name, Url: plugin.DefaultNavUrl, Img: plugin.Info.Logos.Small, } for _, include := range plugin.Includes { if include.Type == "page" && include.AddToNav { link := &dtos.NavLink{ Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/page/" + include.Slug, Text: include.Name, } appLink.Children = append(appLink.Children, link) } if include.Type == "dashboard" && include.AddToNav { link := &dtos.NavLink{ Url: setting.AppSubUrl + "/dashboard/db/" + include.Slug, Text: include.Name, } appLink.Children = append(appLink.Children, link) } } if c.OrgRole == m.ROLE_ADMIN { appLink.Children = append(appLink.Children, &dtos.NavLink{Divider: true}) appLink.Children = append(appLink.Children, &dtos.NavLink{Text: "Plugin Config", Icon: "fa fa-cog", Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/edit"}) } data.MainNavLinks = append(data.MainNavLinks, appLink) } } if c.IsGrafanaAdmin { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Admin", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin", Children: []*dtos.NavLink{ {Text: "Global Users", Url: setting.AppSubUrl + "/admin/users"}, {Text: "Global Orgs", Url: setting.AppSubUrl + "/admin/orgs"}, {Text: "Server Settings", Url: setting.AppSubUrl + "/admin/settings"}, {Text: "Server Stats", Url: setting.AppSubUrl + "/admin/stats"}, }, }) } return &data, nil }
func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { settings, err := getFrontendSettingsMap(c) if err != nil { return nil, err } var data = dtos.IndexViewData{ User: &dtos.CurrentUser{ Id: c.UserId, IsSignedIn: c.IsSignedIn, Login: c.Login, Email: c.Email, Name: c.Name, LightTheme: c.Theme == "light", OrgId: c.OrgId, OrgName: c.OrgName, OrgRole: c.OrgRole, GravatarUrl: dtos.GetGravatarUrl(c.Email), IsGrafanaAdmin: c.IsGrafanaAdmin, }, Settings: settings, AppUrl: setting.AppUrl, AppSubUrl: setting.AppSubUrl, GoogleAnalyticsId: setting.GoogleAnalyticsId, GoogleTagManagerId: setting.GoogleTagManagerId, } if setting.DisableGravatar { data.User.GravatarUrl = setting.AppSubUrl + "/public/img/user_profile.png" } if len(data.User.Name) == 0 { data.User.Name = data.User.Login } themeUrlParam := c.Query("theme") if themeUrlParam == "light" { data.User.LightTheme = true } data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Dashboards", Icon: "fa fa-fw fa-th-large", Url: setting.AppSubUrl + "/", // Children: []*dtos.NavLink{ // {Text: "Playlists", Icon: "fa fa-fw fa-list", Url: setting.AppSubUrl + "/playlists"}, // {Text: "Snapshots", Icon: "fa-fw icon-gf icon-gf-snapshot", Url: setting.AppSubUrl + "/dashboard/snapshots"}, // }, }) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{Text: "Playlists", Icon: "fa fa-fw fa-list", Url: setting.AppSubUrl + "/playlists"}) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{Text: "Snapshots", Icon: "fa-fw icon-gf icon-gf-snapshot", Url: setting.AppSubUrl + "/dashboard/snapshots"}) if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", Icon: "fa fa-fw fa-database", Url: setting.AppSubUrl + "/datasources", }) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Apps", Icon: "fa fa-fw fa-cubes", Url: setting.AppSubUrl + "/apps", }) } enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId) if err != nil { return nil, err } for _, plugin := range enabledPlugins.Apps { if plugin.Pinned { pageLink := &dtos.NavLink{ Text: plugin.Name, Url: setting.AppSubUrl + "/apps/" + plugin.Id + "/edit", Img: plugin.Info.Logos.Small, } for _, page := range plugin.Pages { pageLink.Children = append(pageLink.Children, &dtos.NavLink{ Url: setting.AppSubUrl + "/apps/" + plugin.Id + "/page/" + page.Slug, Text: page.Name, }) } data.MainNavLinks = append(data.MainNavLinks, pageLink) } } return &data, nil }
func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { settings, err := getFrontendSettingsMap(c) if err != nil { return nil, err } var data = dtos.IndexViewData{ User: &dtos.CurrentUser{ Id: c.UserId, IsSignedIn: c.IsSignedIn, Login: c.Login, Email: c.Email, Name: c.Name, LightTheme: c.Theme == "light", OrgId: c.OrgId, OrgName: c.OrgName, OrgRole: c.OrgRole, GravatarUrl: dtos.GetGravatarUrl(c.Email), IsGrafanaAdmin: c.IsGrafanaAdmin, }, Settings: settings, AppUrl: setting.AppUrl, AppSubUrl: setting.AppSubUrl, GoogleAnalyticsId: setting.GoogleAnalyticsId, GoogleTagManagerId: setting.GoogleTagManagerId, } if setting.DisableGravatar { data.User.GravatarUrl = setting.AppSubUrl + "/public/img/transparent.png" } if len(data.User.Name) == 0 { data.User.Name = data.User.Login } themeUrlParam := c.Query("theme") if themeUrlParam == "light" { data.User.LightTheme = true } dashboardChildNavs := []*dtos.NavLink{ {Text: "Home", Url: setting.AppSubUrl + "/"}, {Text: "Playlists", Url: setting.AppSubUrl + "/playlists"}, {Text: "Snapshots", Url: setting.AppSubUrl + "/dashboard/snapshots"}, } if c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR { dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Divider: true}) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "New", Url: setting.AppSubUrl + "/dashboard/new"}) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "Import", Url: setting.AppSubUrl + "/import/dashboard"}) } data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Dashboards", Icon: "icon-gf icon-gf-dashboard", Url: setting.AppSubUrl + "/", Children: dashboardChildNavs, }) if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", Icon: "icon-gf icon-gf-datasources", Url: setting.AppSubUrl + "/datasources", }) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Plugins", Icon: "icon-gf icon-gf-apps", Url: setting.AppSubUrl + "/plugins", }) } enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId) if err != nil { return nil, err } for _, plugin := range enabledPlugins.Apps { if plugin.Pinned { pageLink := &dtos.NavLink{ Text: plugin.Name, Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/edit", Img: plugin.Info.Logos.Small, } for _, page := range plugin.Pages { if !page.SuppressNav { pageLink.Children = append(pageLink.Children, &dtos.NavLink{ Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/page/" + page.Slug, Text: page.Name, }) } } data.MainNavLinks = append(data.MainNavLinks, pageLink) } } if c.IsGrafanaAdmin { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Admin", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin", Children: []*dtos.NavLink{ {Text: "Global Users", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin/users"}, {Text: "Global Orgs", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin/orgs"}, {Text: "Server Settings", Icon: "fa fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin/settings"}, {Text: "Server Stats", Icon: "fa-fw fa-cogs", Url: setting.AppSubUrl + "/admin/stats"}, }, }) } return &data, nil }