mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(apps): more work on apps and how apps can include panels
This commit is contained in:
@@ -12,17 +12,19 @@ type AppSettings struct {
|
||||
Pinned bool `json:"pinned"`
|
||||
Module string `json:"module"`
|
||||
Info *plugins.PluginInfo `json:"info"`
|
||||
Pages []*plugins.AppPluginPage `json:"pages"`
|
||||
Pages []plugins.AppPluginPage `json:"pages"`
|
||||
Includes []plugins.AppIncludeInfo `json:"includes"`
|
||||
JsonData map[string]interface{} `json:"jsonData"`
|
||||
}
|
||||
|
||||
func NewAppSettingsDto(def *plugins.AppPlugin, data *models.AppSettings) *AppSettings {
|
||||
dto := &AppSettings{
|
||||
AppId: def.Id,
|
||||
Name: def.Name,
|
||||
Info: &def.Info,
|
||||
Module: def.Module,
|
||||
Pages: def.Pages,
|
||||
AppId: def.Id,
|
||||
Name: def.Name,
|
||||
Info: &def.Info,
|
||||
Module: def.Module,
|
||||
Pages: def.Pages,
|
||||
Includes: def.Includes,
|
||||
}
|
||||
|
||||
if data != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package plugins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
@@ -17,10 +18,17 @@ type AppPluginCss struct {
|
||||
Dark string `json:"dark"`
|
||||
}
|
||||
|
||||
type AppIncludeInfo struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
type AppPlugin struct {
|
||||
FrontendPluginBase
|
||||
Css *AppPluginCss `json:"css"`
|
||||
Pages []*AppPluginPage `json:"pages"`
|
||||
Css *AppPluginCss `json:"css"`
|
||||
Pages []AppPluginPage `json:"pages"`
|
||||
Includes []AppIncludeInfo `json:"-"`
|
||||
|
||||
Pinned bool `json:"-"`
|
||||
Enabled bool `json:"-"`
|
||||
@@ -38,6 +46,19 @@ func (app *AppPlugin) Load(decoder *json.Decoder, pluginDir string) error {
|
||||
|
||||
app.PluginDir = pluginDir
|
||||
app.initFrontendPlugin()
|
||||
|
||||
// check if we have child panels
|
||||
for _, panel := range Panels {
|
||||
if strings.HasPrefix(panel.PluginDir, app.PluginDir) {
|
||||
panel.IncludedInAppId = app.Id
|
||||
app.Includes = append(app.Includes, AppIncludeInfo{
|
||||
Name: panel.Name,
|
||||
Id: panel.Id,
|
||||
Type: panel.Type,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Apps[app.Id] = app
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,21 +8,22 @@ import (
|
||||
|
||||
type FrontendPluginBase struct {
|
||||
PluginBase
|
||||
Module string `json:"module"`
|
||||
StaticRoot string `json:"staticRoot"`
|
||||
Module string `json:"module"`
|
||||
StaticRoot string `json:"staticRoot"`
|
||||
StaticRootAbs string `json:"-"`
|
||||
}
|
||||
|
||||
func (fp *FrontendPluginBase) initFrontendPlugin() {
|
||||
if fp.StaticRoot != "" {
|
||||
fp.StaticRootAbs = filepath.Join(fp.PluginDir, fp.StaticRoot)
|
||||
StaticRoutes = append(StaticRoutes, &PluginStaticRoute{
|
||||
Directory: filepath.Join(fp.PluginDir, fp.StaticRoot),
|
||||
Directory: fp.StaticRootAbs,
|
||||
PluginId: fp.Id,
|
||||
})
|
||||
}
|
||||
|
||||
fp.Info.Logos.Small = evalRelativePluginUrlPath(fp.Info.Logos.Small, fp.Id)
|
||||
fp.Info.Logos.Large = evalRelativePluginUrlPath(fp.Info.Logos.Large, fp.Id)
|
||||
|
||||
fp.handleModuleDefaults()
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,13 @@ type PluginLoader interface {
|
||||
}
|
||||
|
||||
type PluginBase struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Id string `json:"id"`
|
||||
App string `json:"app"`
|
||||
Info PluginInfo `json:"info"`
|
||||
PluginDir string `json:"-"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Id string `json:"id"`
|
||||
Info PluginInfo `json:"info"`
|
||||
|
||||
IncludedInAppId string `json:"-"`
|
||||
PluginDir string `json:"-"`
|
||||
}
|
||||
|
||||
type PluginInfo struct {
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@@ -122,28 +119,6 @@ func (scanner *PluginScanner) walker(currentPath string, f os.FileInfo, err erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func interpolatePluginJson(reader io.Reader, pluginCommon *PluginBase) (io.Reader, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(reader)
|
||||
jsonStr := buf.String() //
|
||||
|
||||
tmpl, err := template.New("json").Parse(jsonStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"PluginPublicRoot": "public/plugins/" + pluginCommon.Id,
|
||||
}
|
||||
|
||||
var resultBuffer bytes.Buffer
|
||||
if err := tmpl.ExecuteTemplate(&resultBuffer, "json", data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytes.NewReader(resultBuffer.Bytes()), nil
|
||||
}
|
||||
|
||||
func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
|
||||
currentDir := filepath.Dir(pluginJsonFilePath)
|
||||
reader, err := os.Open(pluginJsonFilePath)
|
||||
@@ -163,20 +138,13 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
|
||||
return errors.New("Did not find type and id property in plugin.json")
|
||||
}
|
||||
|
||||
reader.Seek(0, 0)
|
||||
if newReader, err := interpolatePluginJson(reader, &pluginCommon); err != nil {
|
||||
return err
|
||||
} else {
|
||||
jsonParser = json.NewDecoder(newReader)
|
||||
}
|
||||
|
||||
var loader PluginLoader
|
||||
|
||||
if pluginGoType, exists := PluginTypes[pluginCommon.Type]; !exists {
|
||||
return errors.New("Unkown plugin type " + pluginCommon.Type)
|
||||
} else {
|
||||
loader = reflect.New(reflect.TypeOf(pluginGoType)).Interface().(PluginLoader)
|
||||
}
|
||||
|
||||
reader.Seek(0, 0)
|
||||
return loader.Load(jsonParser, currentDir)
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@ func GetEnabledPlugins(orgId int64) (*EnabledPlugins, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seenPanels := make(map[string]bool)
|
||||
seenApi := make(map[string]bool)
|
||||
enabledApps := make(map[string]bool)
|
||||
|
||||
for appId, installedApp := range Apps {
|
||||
var app AppPlugin
|
||||
@@ -42,32 +41,36 @@ func GetEnabledPlugins(orgId int64) (*EnabledPlugins, error) {
|
||||
}
|
||||
|
||||
if app.Enabled {
|
||||
enabledApps[app.Id] = true
|
||||
enabledPlugins.Apps = append(enabledPlugins.Apps, &app)
|
||||
}
|
||||
}
|
||||
|
||||
isPluginEnabled := func(appId string) bool {
|
||||
if appId == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
_, ok := enabledApps[appId]
|
||||
return ok
|
||||
}
|
||||
|
||||
// add all plugins that are not part of an App.
|
||||
for d, installedDs := range DataSources {
|
||||
if installedDs.App == "" {
|
||||
enabledPlugins.DataSources[d] = installedDs
|
||||
for dsId, ds := range DataSources {
|
||||
if isPluginEnabled(ds.IncludedInAppId) {
|
||||
enabledPlugins.DataSources[dsId] = ds
|
||||
}
|
||||
}
|
||||
|
||||
for p, panel := range Panels {
|
||||
if panel.App == "" {
|
||||
if _, ok := seenPanels[p]; !ok {
|
||||
seenPanels[p] = true
|
||||
enabledPlugins.Panels = append(enabledPlugins.Panels, panel)
|
||||
}
|
||||
for _, panel := range Panels {
|
||||
if isPluginEnabled(panel.IncludedInAppId) {
|
||||
enabledPlugins.Panels = append(enabledPlugins.Panels, panel)
|
||||
}
|
||||
}
|
||||
|
||||
for a, api := range ApiPlugins {
|
||||
if api.App == "" {
|
||||
if _, ok := seenApi[a]; !ok {
|
||||
seenApi[a] = true
|
||||
enabledPlugins.ApiList = append(enabledPlugins.ApiList, api)
|
||||
}
|
||||
for _, api := range ApiPlugins {
|
||||
if isPluginEnabled(api.IncludedInAppId) {
|
||||
enabledPlugins.ApiList = append(enabledPlugins.ApiList, api)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user