mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(plugins): began refactoring AppSettings -> PluginSettings, and have the plugins list view and plugin edit view be common for all plugins
This commit is contained in:
parent
30f3b55baf
commit
8db7cf49a6
@ -126,9 +126,9 @@ func Register(r *macaron.Macaron) {
|
|||||||
r.Patch("/invites/:code/revoke", wrap(RevokeInvite))
|
r.Patch("/invites/:code/revoke", wrap(RevokeInvite))
|
||||||
|
|
||||||
// apps
|
// apps
|
||||||
r.Get("/apps", wrap(GetOrgAppsList))
|
r.Get("/plugins", wrap(GetPluginList))
|
||||||
r.Get("/apps/:appId/settings", wrap(GetAppSettingsById))
|
r.Get("/plugins/:pluginId/settings", wrap(GetPluginSettingById))
|
||||||
r.Post("/apps/:appId/settings", bind(m.UpdateAppSettingsCmd{}), wrap(UpdateAppSettings))
|
r.Post("/plugins/:pluginId/settings", bind(m.UpdatePluginSettingCmd{}), wrap(UpdatePluginSetting))
|
||||||
}, reqOrgAdmin)
|
}, reqOrgAdmin)
|
||||||
|
|
||||||
// create new org
|
// create new org
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/grafana/grafana/pkg/api/dtos"
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetOrgAppsList(c *middleware.Context) Response {
|
|
||||||
orgApps, err := plugins.GetOrgAppSettings(c.OrgId)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return ApiError(500, "Failed to list of apps", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make([]*dtos.AppSettings, 0)
|
|
||||||
for _, app := range plugins.Apps {
|
|
||||||
orgApp := orgApps[app.Id]
|
|
||||||
result = append(result, dtos.NewAppSettingsDto(app, orgApp))
|
|
||||||
}
|
|
||||||
|
|
||||||
return Json(200, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAppSettingsById(c *middleware.Context) Response {
|
|
||||||
appId := c.Params(":appId")
|
|
||||||
|
|
||||||
if pluginDef, exists := plugins.Apps[appId]; !exists {
|
|
||||||
return ApiError(404, "PluginId not found, no installed plugin with that id", nil)
|
|
||||||
} else {
|
|
||||||
orgApps, err := plugins.GetOrgAppSettings(c.OrgId)
|
|
||||||
if err != nil {
|
|
||||||
return ApiError(500, "Failed to get org app settings ", nil)
|
|
||||||
}
|
|
||||||
orgApp := orgApps[appId]
|
|
||||||
|
|
||||||
return Json(200, dtos.NewAppSettingsDto(pluginDef, orgApp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateAppSettings(c *middleware.Context, cmd m.UpdateAppSettingsCmd) Response {
|
|
||||||
appId := c.Params(":appId")
|
|
||||||
|
|
||||||
cmd.OrgId = c.OrgId
|
|
||||||
cmd.AppId = appId
|
|
||||||
|
|
||||||
if _, ok := plugins.Apps[cmd.AppId]; !ok {
|
|
||||||
return ApiError(404, "App type not installed.", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := bus.Dispatch(&cmd)
|
|
||||||
if err != nil {
|
|
||||||
return ApiError(500, "Failed to update App Plugin", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ApiSuccess("App updated")
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppSettings struct {
|
type PluginSetting struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
AppId string `json:"appId"`
|
AppId string `json:"appId"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
@ -18,8 +18,17 @@ type AppSettings struct {
|
|||||||
JsonData map[string]interface{} `json:"jsonData"`
|
JsonData map[string]interface{} `json:"jsonData"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAppSettingsDto(def *plugins.AppPlugin, data *models.AppSettings) *AppSettings {
|
type PluginListItem struct {
|
||||||
dto := &AppSettings{
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
PluginId string `json:"pluginId"`
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
Pinned bool `json:"pinned"`
|
||||||
|
Info *plugins.PluginInfo `json:"info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPluginSettingDto(def *plugins.AppPlugin, data *models.PluginSetting) *PluginSetting {
|
||||||
|
dto := &PluginSetting{
|
||||||
AppId: def.Id,
|
AppId: def.Id,
|
||||||
Name: def.Name,
|
Name: def.Name,
|
||||||
Info: &def.Info,
|
Info: &def.Info,
|
68
pkg/api/plugin_setting.go
Normal file
68
pkg/api/plugin_setting.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/grafana/grafana/pkg/api/dtos"
|
||||||
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetPluginList(c *middleware.Context) Response {
|
||||||
|
pluginSettingsMap, err := plugins.GetPluginSettings(c.OrgId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return ApiError(500, "Failed to get list of plugins", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]*dtos.PluginListItem, 0)
|
||||||
|
for _, pluginDef := range plugins.Plugins {
|
||||||
|
listItem := &dtos.PluginListItem{
|
||||||
|
PluginId: pluginDef.Id,
|
||||||
|
Name: pluginDef.Name,
|
||||||
|
Type: pluginDef.Type,
|
||||||
|
Info: &pluginDef.Info,
|
||||||
|
}
|
||||||
|
|
||||||
|
if pluginSetting, exists := pluginSettingsMap[pluginDef.Id]; exists {
|
||||||
|
listItem.Enabled = pluginSetting.Enabled
|
||||||
|
listItem.Pinned = pluginSetting.Pinned
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, listItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Json(200, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPluginSettingById(c *middleware.Context) Response {
|
||||||
|
pluginId := c.Params(":pluginId")
|
||||||
|
|
||||||
|
if pluginDef, exists := plugins.Apps[pluginId]; !exists {
|
||||||
|
return ApiError(404, "PluginId not found, no installed plugin with that id", nil)
|
||||||
|
} else {
|
||||||
|
query := m.GetPluginSettingByIdQuery{PluginId: pluginId, OrgId: c.OrgId}
|
||||||
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
|
return ApiError(500, "Failed to get login settings", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Json(200, dtos.NewPluginSettingDto(pluginDef, query.Result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdatePluginSetting(c *middleware.Context, cmd m.UpdatePluginSettingCmd) Response {
|
||||||
|
pluginId := c.Params(":pluginId")
|
||||||
|
|
||||||
|
cmd.OrgId = c.OrgId
|
||||||
|
cmd.PluginId = pluginId
|
||||||
|
|
||||||
|
if _, ok := plugins.Apps[cmd.PluginId]; !ok {
|
||||||
|
return ApiError(404, "Plugin not installed.", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bus.Dispatch(&cmd); err != nil {
|
||||||
|
return ApiError(500, "Failed to update plugin setting", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiSuccess("Plugin settings updated")
|
||||||
|
}
|
@ -26,7 +26,7 @@ type templateData struct {
|
|||||||
func getHeaders(route *plugins.AppPluginRoute, orgId int64, appId string) (http.Header, error) {
|
func getHeaders(route *plugins.AppPluginRoute, orgId int64, appId string) (http.Header, error) {
|
||||||
result := http.Header{}
|
result := http.Header{}
|
||||||
|
|
||||||
query := m.GetAppSettingByAppIdQuery{OrgId: orgId, AppId: appId}
|
query := m.GetPluginSettingByIdQuery{OrgId: orgId, PluginId: appId}
|
||||||
|
|
||||||
if err := bus.Dispatch(&query); err != nil {
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -9,12 +9,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrAppSettingNotFound = errors.New("AppSetting not found")
|
ErrPluginSettingNotFound = errors.New("Plugin setting not found")
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppSettings struct {
|
type PluginSetting struct {
|
||||||
Id int64
|
Id int64
|
||||||
AppId string
|
PluginId string
|
||||||
OrgId int64
|
OrgId int64
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Pinned bool
|
Pinned bool
|
||||||
@ -39,17 +39,17 @@ func (s SecureJsonData) Decrypt() map[string]string {
|
|||||||
// COMMANDS
|
// COMMANDS
|
||||||
|
|
||||||
// Also acts as api DTO
|
// Also acts as api DTO
|
||||||
type UpdateAppSettingsCmd struct {
|
type UpdatePluginSettingCmd struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
Pinned bool `json:"pinned"`
|
Pinned bool `json:"pinned"`
|
||||||
JsonData map[string]interface{} `json:"jsonData"`
|
JsonData map[string]interface{} `json:"jsonData"`
|
||||||
SecureJsonData map[string]string `json:"secureJsonData"`
|
SecureJsonData map[string]string `json:"secureJsonData"`
|
||||||
|
|
||||||
AppId string `json:"-"`
|
PluginId string `json:"-"`
|
||||||
OrgId int64 `json:"-"`
|
OrgId int64 `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *UpdateAppSettingsCmd) GetEncryptedJsonData() SecureJsonData {
|
func (cmd *UpdatePluginSettingCmd) GetEncryptedJsonData() SecureJsonData {
|
||||||
encrypted := make(SecureJsonData)
|
encrypted := make(SecureJsonData)
|
||||||
for key, data := range cmd.SecureJsonData {
|
for key, data := range cmd.SecureJsonData {
|
||||||
encrypted[key] = util.Encrypt([]byte(data), setting.SecretKey)
|
encrypted[key] = util.Encrypt([]byte(data), setting.SecretKey)
|
||||||
@ -59,13 +59,13 @@ func (cmd *UpdateAppSettingsCmd) GetEncryptedJsonData() SecureJsonData {
|
|||||||
|
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// QUERIES
|
// QUERIES
|
||||||
type GetAppSettingsQuery struct {
|
type GetPluginSettingsQuery struct {
|
||||||
OrgId int64
|
OrgId int64
|
||||||
Result []*AppSettings
|
Result []*PluginSetting
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetAppSettingByAppIdQuery struct {
|
type GetPluginSettingByIdQuery struct {
|
||||||
AppId string
|
PluginId string
|
||||||
OrgId int64
|
OrgId int64
|
||||||
Result *AppSettings
|
Result *PluginSetting
|
||||||
}
|
}
|
@ -5,44 +5,40 @@ import (
|
|||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetOrgAppSettings(orgId int64) (map[string]*m.AppSettings, error) {
|
func GetPluginSettings(orgId int64) (map[string]*m.PluginSetting, error) {
|
||||||
query := m.GetAppSettingsQuery{OrgId: orgId}
|
query := m.GetPluginSettingsQuery{OrgId: orgId}
|
||||||
|
|
||||||
if err := bus.Dispatch(&query); err != nil {
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
orgAppsMap := make(map[string]*m.AppSettings)
|
pluginMap := make(map[string]*m.PluginSetting)
|
||||||
for _, orgApp := range query.Result {
|
for _, plug := range query.Result {
|
||||||
orgAppsMap[orgApp.AppId] = orgApp
|
pluginMap[plug.PluginId] = plug
|
||||||
}
|
}
|
||||||
|
|
||||||
return orgAppsMap, nil
|
return pluginMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEnabledPlugins(orgId int64) (*EnabledPlugins, error) {
|
func GetEnabledPlugins(orgId int64) (*EnabledPlugins, error) {
|
||||||
enabledPlugins := NewEnabledPlugins()
|
enabledPlugins := NewEnabledPlugins()
|
||||||
orgApps, err := GetOrgAppSettings(orgId)
|
orgPlugins, err := GetPluginSettings(orgId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledApps := make(map[string]bool)
|
enabledApps := make(map[string]bool)
|
||||||
|
|
||||||
for appId, installedApp := range Apps {
|
for pluginId, app := range Apps {
|
||||||
var app AppPlugin
|
|
||||||
app = *installedApp
|
|
||||||
|
|
||||||
// check if the app is stored in the DB for this org and if so, use the
|
if b, ok := orgPlugins[pluginId]; ok {
|
||||||
// state stored there.
|
|
||||||
if b, ok := orgApps[appId]; ok {
|
|
||||||
app.Enabled = b.Enabled
|
app.Enabled = b.Enabled
|
||||||
app.Pinned = b.Pinned
|
app.Pinned = b.Pinned
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.Enabled {
|
if app.Enabled {
|
||||||
enabledApps[app.Id] = true
|
enabledApps[pluginId] = true
|
||||||
enabledPlugins.Apps = append(enabledPlugins.Apps, &app)
|
enabledPlugins.Apps = append(enabledPlugins.Apps, app)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
package sqlstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
|
||||||
"github.com/grafana/grafana/pkg/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
bus.AddHandler("sql", GetAppSettings)
|
|
||||||
bus.AddHandler("sql", GetAppSettingByAppId)
|
|
||||||
bus.AddHandler("sql", UpdateAppSettings)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAppSettings(query *m.GetAppSettingsQuery) error {
|
|
||||||
sess := x.Where("org_id=?", query.OrgId)
|
|
||||||
|
|
||||||
query.Result = make([]*m.AppSettings, 0)
|
|
||||||
return sess.Find(&query.Result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAppSettingByAppId(query *m.GetAppSettingByAppIdQuery) error {
|
|
||||||
appSetting := m.AppSettings{OrgId: query.OrgId, AppId: query.AppId}
|
|
||||||
has, err := x.Get(&appSetting)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if has == false {
|
|
||||||
return m.ErrAppSettingNotFound
|
|
||||||
}
|
|
||||||
query.Result = &appSetting
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateAppSettings(cmd *m.UpdateAppSettingsCmd) error {
|
|
||||||
return inTransaction2(func(sess *session) error {
|
|
||||||
var app m.AppSettings
|
|
||||||
|
|
||||||
exists, err := sess.Where("org_id=? and app_id=?", cmd.OrgId, cmd.AppId).Get(&app)
|
|
||||||
sess.UseBool("enabled")
|
|
||||||
sess.UseBool("pinned")
|
|
||||||
if !exists {
|
|
||||||
app = m.AppSettings{
|
|
||||||
AppId: cmd.AppId,
|
|
||||||
OrgId: cmd.OrgId,
|
|
||||||
Enabled: cmd.Enabled,
|
|
||||||
Pinned: cmd.Pinned,
|
|
||||||
JsonData: cmd.JsonData,
|
|
||||||
SecureJsonData: cmd.GetEncryptedJsonData(),
|
|
||||||
Created: time.Now(),
|
|
||||||
Updated: time.Now(),
|
|
||||||
}
|
|
||||||
_, err = sess.Insert(&app)
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
for key, data := range cmd.SecureJsonData {
|
|
||||||
app.SecureJsonData[key] = util.Encrypt([]byte(data), setting.SecretKey)
|
|
||||||
}
|
|
||||||
app.SecureJsonData = cmd.GetEncryptedJsonData()
|
|
||||||
app.Updated = time.Now()
|
|
||||||
app.Enabled = cmd.Enabled
|
|
||||||
app.JsonData = cmd.JsonData
|
|
||||||
app.Pinned = cmd.Pinned
|
|
||||||
_, err = sess.Id(app.Id).Update(&app)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
@ -4,12 +4,12 @@ import . "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
|||||||
|
|
||||||
func addAppSettingsMigration(mg *Migrator) {
|
func addAppSettingsMigration(mg *Migrator) {
|
||||||
|
|
||||||
appSettingsV2 := Table{
|
pluginSettingTable := Table{
|
||||||
Name: "app_settings",
|
Name: "plugin_setting",
|
||||||
Columns: []*Column{
|
Columns: []*Column{
|
||||||
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||||
{Name: "org_id", Type: DB_BigInt, Nullable: true},
|
{Name: "org_id", Type: DB_BigInt, Nullable: true},
|
||||||
{Name: "app_id", Type: DB_NVarchar, Length: 255, Nullable: false},
|
{Name: "plugin_id", Type: DB_NVarchar, Length: 255, Nullable: false},
|
||||||
{Name: "enabled", Type: DB_Bool, Nullable: false},
|
{Name: "enabled", Type: DB_Bool, Nullable: false},
|
||||||
{Name: "pinned", Type: DB_Bool, Nullable: false},
|
{Name: "pinned", Type: DB_Bool, Nullable: false},
|
||||||
{Name: "json_data", Type: DB_Text, Nullable: true},
|
{Name: "json_data", Type: DB_Text, Nullable: true},
|
||||||
@ -18,14 +18,12 @@ func addAppSettingsMigration(mg *Migrator) {
|
|||||||
{Name: "updated", Type: DB_DateTime, Nullable: false},
|
{Name: "updated", Type: DB_DateTime, Nullable: false},
|
||||||
},
|
},
|
||||||
Indices: []*Index{
|
Indices: []*Index{
|
||||||
{Cols: []string{"org_id", "app_id"}, Type: UniqueIndex},
|
{Cols: []string{"org_id", "plugin_id"}, Type: UniqueIndex},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mg.AddMigration("Drop old table app_settings v1", NewDropTableMigration("app_settings"))
|
mg.AddMigration("create plugin_setting table", NewAddTableMigration(pluginSettingTable))
|
||||||
|
|
||||||
mg.AddMigration("create app_settings table v2", NewAddTableMigration(appSettingsV2))
|
|
||||||
|
|
||||||
//------- indexes ------------------
|
//------- indexes ------------------
|
||||||
addTableIndicesMigrations(mg, "v3", appSettingsV2)
|
addTableIndicesMigrations(mg, "v1", pluginSettingTable)
|
||||||
}
|
}
|
70
pkg/services/sqlstore/plugin_setting.go
Normal file
70
pkg/services/sqlstore/plugin_setting.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package sqlstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
|
"github.com/grafana/grafana/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
bus.AddHandler("sql", GetPluginSettings)
|
||||||
|
bus.AddHandler("sql", GetPluginSettingById)
|
||||||
|
bus.AddHandler("sql", UpdatePluginSetting)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPluginSettings(query *m.GetPluginSettingsQuery) error {
|
||||||
|
sess := x.Where("org_id=?", query.OrgId)
|
||||||
|
|
||||||
|
query.Result = make([]*m.PluginSetting, 0)
|
||||||
|
return sess.Find(&query.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPluginSettingById(query *m.GetPluginSettingByIdQuery) error {
|
||||||
|
pluginSetting := m.PluginSetting{OrgId: query.OrgId, PluginId: query.PluginId}
|
||||||
|
has, err := x.Get(&pluginSetting)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if has == false {
|
||||||
|
return m.ErrPluginSettingNotFound
|
||||||
|
}
|
||||||
|
query.Result = &pluginSetting
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdatePluginSetting(cmd *m.UpdatePluginSettingCmd) error {
|
||||||
|
return inTransaction2(func(sess *session) error {
|
||||||
|
var pluginSetting m.PluginSetting
|
||||||
|
|
||||||
|
exists, err := sess.Where("org_id=? and plugin_id=?", cmd.OrgId, cmd.PluginId).Get(&pluginSetting)
|
||||||
|
sess.UseBool("enabled")
|
||||||
|
sess.UseBool("pinned")
|
||||||
|
if !exists {
|
||||||
|
pluginSetting = m.PluginSetting{
|
||||||
|
PluginId: cmd.PluginId,
|
||||||
|
OrgId: cmd.OrgId,
|
||||||
|
Enabled: cmd.Enabled,
|
||||||
|
Pinned: cmd.Pinned,
|
||||||
|
JsonData: cmd.JsonData,
|
||||||
|
SecureJsonData: cmd.GetEncryptedJsonData(),
|
||||||
|
Created: time.Now(),
|
||||||
|
Updated: time.Now(),
|
||||||
|
}
|
||||||
|
_, err = sess.Insert(&pluginSetting)
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
for key, data := range cmd.SecureJsonData {
|
||||||
|
pluginSetting.SecureJsonData[key] = util.Encrypt([]byte(data), setting.SecretKey)
|
||||||
|
}
|
||||||
|
pluginSetting.SecureJsonData = cmd.GetEncryptedJsonData()
|
||||||
|
pluginSetting.Updated = time.Now()
|
||||||
|
pluginSetting.Enabled = cmd.Enabled
|
||||||
|
pluginSetting.JsonData = cmd.JsonData
|
||||||
|
pluginSetting.Pinned = cmd.Pinned
|
||||||
|
_, err = sess.Id(pluginSetting.Id).Update(&pluginSetting)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -11,7 +11,7 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
$locationProvider.html5Mode(true);
|
$locationProvider.html5Mode(true);
|
||||||
|
|
||||||
var loadOrgBundle = new BundleLoader('app/features/org/all');
|
var loadOrgBundle = new BundleLoader('app/features/org/all');
|
||||||
var loadAppsBundle = new BundleLoader('app/features/apps/all');
|
var loadPluginsBundle = new BundleLoader('app/features/plugins/all');
|
||||||
var loadAdminBundle = new BundleLoader('app/features/admin/admin');
|
var loadAdminBundle = new BundleLoader('app/features/admin/admin');
|
||||||
|
|
||||||
$routeProvider
|
$routeProvider
|
||||||
@ -165,23 +165,23 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
controller : 'SnapshotsCtrl',
|
controller : 'SnapshotsCtrl',
|
||||||
controllerAs: 'ctrl',
|
controllerAs: 'ctrl',
|
||||||
})
|
})
|
||||||
.when('/apps', {
|
.when('/plugins', {
|
||||||
templateUrl: 'public/app/features/apps/partials/list.html',
|
templateUrl: 'public/app/features/plugins/partials/list.html',
|
||||||
controller: 'AppListCtrl',
|
controller: 'PluginListCtrl',
|
||||||
controllerAs: 'ctrl',
|
controllerAs: 'ctrl',
|
||||||
resolve: loadAppsBundle,
|
resolve: loadPluginsBundle,
|
||||||
})
|
})
|
||||||
.when('/apps/:appId/edit', {
|
.when('/plugins/:pluginId/edit', {
|
||||||
templateUrl: 'public/app/features/apps/partials/edit.html',
|
templateUrl: 'public/app/features/plugins/partials/edit.html',
|
||||||
controller: 'AppEditCtrl',
|
controller: 'PluginEditCtrl',
|
||||||
controllerAs: 'ctrl',
|
controllerAs: 'ctrl',
|
||||||
resolve: loadAppsBundle,
|
resolve: loadPluginsBundle,
|
||||||
})
|
})
|
||||||
.when('/apps/:appId/page/:slug', {
|
.when('/plugins/:pluginId/page/:slug', {
|
||||||
templateUrl: 'public/app/features/apps/partials/page.html',
|
templateUrl: 'public/app/features/plugins/partials/page.html',
|
||||||
controller: 'AppPageCtrl',
|
controller: 'AppPageCtrl',
|
||||||
controllerAs: 'ctrl',
|
controllerAs: 'ctrl',
|
||||||
resolve: loadAppsBundle,
|
resolve: loadPluginsBundle,
|
||||||
})
|
})
|
||||||
.when('/global-alerts', {
|
.when('/global-alerts', {
|
||||||
templateUrl: 'public/app/features/dashboard/partials/globalAlerts.html',
|
templateUrl: 'public/app/features/dashboard/partials/globalAlerts.html',
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
///<reference path="../../headers/common.d.ts" />
|
|
||||||
|
|
||||||
import angular from 'angular';
|
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
export class AppEditCtrl {
|
|
||||||
appModel: any;
|
|
||||||
appId: any;
|
|
||||||
includedPanels: any;
|
|
||||||
includedDatasources: any;
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
constructor(private backendSrv: any, private $routeParams: any) {
|
|
||||||
this.appModel = {};
|
|
||||||
this.appId = $routeParams.appId;
|
|
||||||
|
|
||||||
this.backendSrv.get(`/api/org/apps/${this.appId}/settings`).then(result => {
|
|
||||||
this.appModel = result;
|
|
||||||
this.includedPanels = _.where(result.includes, {type: 'panel'});
|
|
||||||
this.includedDatasources = _.where(result.includes, {type: 'datasource'});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
|
||||||
var updateCmd = _.extend({
|
|
||||||
appId: this.appModel.appId,
|
|
||||||
orgId: this.appModel.orgId,
|
|
||||||
enabled: this.appModel.enabled,
|
|
||||||
pinned: this.appModel.pinned,
|
|
||||||
jsonData: this.appModel.jsonData,
|
|
||||||
secureJsonData: this.appModel.secureJsonData,
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
this.backendSrv.post(`/api/org/apps/${this.appId}/settings`, updateCmd).then(function() {
|
|
||||||
window.location.href = window.location.href;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleEnabled() {
|
|
||||||
this.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
togglePinned() {
|
|
||||||
this.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
angular.module('grafana.controllers').controller('AppEditCtrl', AppEditCtrl);
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
///<reference path="../../headers/common.d.ts" />
|
|
||||||
|
|
||||||
import angular from 'angular';
|
|
||||||
|
|
||||||
export class AppListCtrl {
|
|
||||||
apps: any[];
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
constructor(private backendSrv: any) {
|
|
||||||
|
|
||||||
this.backendSrv.get('api/org/apps').then(apps => {
|
|
||||||
this.apps = apps;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
angular.module('grafana.controllers').controller('AppListCtrl', AppListCtrl);
|
|
@ -1,47 +0,0 @@
|
|||||||
<navbar title="Plugins" icon="icon-gf icon-gf-apps" title-url="apps">
|
|
||||||
</navbar>
|
|
||||||
|
|
||||||
<div class="page-container">
|
|
||||||
<div class="page-header">
|
|
||||||
<h1>Plugins</h1>
|
|
||||||
</div>
|
|
||||||
<div ng-if="!ctrl.apps">
|
|
||||||
<em>No apps defined</em>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="filter-list">
|
|
||||||
<li ng-repeat="app in ctrl.apps">
|
|
||||||
<ul class="filter-list-card">
|
|
||||||
<li class="filter-list-card-image">
|
|
||||||
<img ng-src="{{app.info.logos.small}}">
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div class="filter-list-card-controls">
|
|
||||||
<div class="filter-list-card-config">
|
|
||||||
<a href="apps/{{app.appId}}/edit">
|
|
||||||
<i class="fa fa-cog"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span class="filter-list-card-title">
|
|
||||||
<a href="apps/{{app.appId}}/edit">
|
|
||||||
{{app.name}}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<span class="label label-info" ng-if="app.enabled">
|
|
||||||
Enabled
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="label label-info" ng-if="app.pinned">
|
|
||||||
Pinned
|
|
||||||
</span>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span class="filter-list-card-status">
|
|
||||||
<span class="filter-list-card-state">Dashboards: 1</span>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
49
public/app/features/plugins/edit_ctrl.ts
Normal file
49
public/app/features/plugins/edit_ctrl.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
///<reference path="../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import angular from 'angular';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
export class PluginEditCtrl {
|
||||||
|
model: any;
|
||||||
|
pluginId: any;
|
||||||
|
includedPanels: any;
|
||||||
|
includedDatasources: any;
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
constructor(private backendSrv: any, private $routeParams: any) {
|
||||||
|
this.model = {};
|
||||||
|
this.pluginId = $routeParams.pluginId;
|
||||||
|
|
||||||
|
this.backendSrv.get(`/api/org/plugins/${this.pluginId}/settings`).then(result => {
|
||||||
|
this.model = result;
|
||||||
|
this.includedPanels = _.where(result.includes, {type: 'panel'});
|
||||||
|
this.includedDatasources = _.where(result.includes, {type: 'datasource'});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
var updateCmd = _.extend({
|
||||||
|
pluginId: this.model.pluginId,
|
||||||
|
orgId: this.model.orgId,
|
||||||
|
enabled: this.model.enabled,
|
||||||
|
pinned: this.model.pinned,
|
||||||
|
jsonData: this.model.jsonData,
|
||||||
|
secureJsonData: this.model.secureJsonData,
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
this.backendSrv.post(`/api/org/plugins/${this.pluginId}/settings`, updateCmd).then(function() {
|
||||||
|
window.location.href = window.location.href;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleEnabled() {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
togglePinned() {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.module('grafana.controllers').controller('PluginEditCtrl', PluginEditCtrl);
|
||||||
|
|
17
public/app/features/plugins/list_ctrl.ts
Normal file
17
public/app/features/plugins/list_ctrl.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
///<reference path="../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import angular from 'angular';
|
||||||
|
|
||||||
|
export class PluginListCtrl {
|
||||||
|
plugins: any[];
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
constructor(private backendSrv: any) {
|
||||||
|
|
||||||
|
this.backendSrv.get('api/org/plugins').then(plugins => {
|
||||||
|
this.plugins = plugins;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.module('grafana.controllers').controller('PluginListCtrl', PluginListCtrl);
|
42
public/app/features/plugins/partials/list.html
Normal file
42
public/app/features/plugins/partials/list.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<navbar title="Plugins" icon="icon-gf icon-gf-apps" title-url="plugins">
|
||||||
|
</navbar>
|
||||||
|
|
||||||
|
<div class="page-container">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>Plugins</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="filter-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><strong>Name</strong></th>
|
||||||
|
<th><strong>Type</strong></th>
|
||||||
|
<th style="width: 60px;"></th>
|
||||||
|
<th style="width: 80px;"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="plugin in ctrl.plugins">
|
||||||
|
<td>
|
||||||
|
<a href="plugins/{{plugin.pluginId}}/edit">
|
||||||
|
{{plugin.name}}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{plugin.type}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="label label-info" ng-if="plugin.enabled">Enabled</span>
|
||||||
|
<span class="label label-info" ng-if="plugin.pinned">Pinned</span>
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<a href="plugins/{{plugin.pluginId}}/edit" class="btn btn-inverse btn-small">
|
||||||
|
<i class="fa fa-edit"></i>
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in New Issue
Block a user