diff --git a/pkg/api/api.go b/pkg/api/api.go index ae523b662a6..0ffe5b9508f 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -41,8 +41,8 @@ func Register(r *macaron.Macaron) { r.Get("/admin/orgs", reqGrafanaAdmin, Index) r.Get("/admin/orgs/edit/:id", reqGrafanaAdmin, Index) - r.Get("/org/apps", reqSignedIn, Index) - r.Get("/org/apps/edit/*", reqSignedIn, Index) + r.Get("/apps", reqSignedIn, Index) + r.Get("/apps/edit/*", reqSignedIn, Index) r.Get("/dashboard/*", reqSignedIn, Index) r.Get("/dashboard-solo/*", reqSignedIn, Index) @@ -119,8 +119,9 @@ func Register(r *macaron.Macaron) { r.Patch("/invites/:code/revoke", wrap(RevokeInvite)) // apps - r.Get("/apps", wrap(GetAppPlugins)) - r.Post("/apps", bind(m.UpdateAppPluginCmd{}), wrap(UpdateAppPlugin)) + r.Get("/apps", wrap(GetOrgAppsList)) + r.Get("/apps/:appId/settings", wrap(GetAppSettingsById)) + r.Post("/apps/:appId/settings", bind(m.UpdateAppSettingsCmd{}), wrap(UpdateAppSettings)) }, reqOrgAdmin) // create new org diff --git a/pkg/api/app_plugin.go b/pkg/api/app_plugin.go deleted file mode 100644 index bcab5fa4788..00000000000 --- a/pkg/api/app_plugin.go +++ /dev/null @@ -1,63 +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 GetAppPlugins(c *middleware.Context) Response { - query := m.GetAppPluginsQuery{OrgId: c.OrgId} - - if err := bus.Dispatch(&query); err != nil { - return ApiError(500, "Failed to list Plugin Bundles", err) - } - - translateToDto := func(app *plugins.AppPlugin) *dtos.AppPlugin { - return &dtos.AppPlugin{ - Name: app.Name, - Type: app.Type, - Enabled: app.Enabled, - Pinned: app.Pinned, - Module: app.Module, - Info: &app.Info, - } - } - - seenApps := make(map[string]bool) - result := make([]*dtos.AppPlugin, 0) - for _, orgApp := range query.Result { - if def, ok := plugins.Apps[orgApp.Type]; ok { - pluginDto := translateToDto(def) - pluginDto.Enabled = orgApp.Enabled - pluginDto.JsonData = orgApp.JsonData - result = append(result, pluginDto) - seenApps[orgApp.Type] = true - } - } - - for _, app := range plugins.Apps { - if _, ok := seenApps[app.Type]; !ok { - result = append(result, translateToDto(app)) - } - } - - return Json(200, result) -} - -func UpdateAppPlugin(c *middleware.Context, cmd m.UpdateAppPluginCmd) Response { - cmd.OrgId = c.OrgId - - if _, ok := plugins.Apps[cmd.Type]; !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") -} diff --git a/pkg/api/app_settings.go b/pkg/api/app_settings.go new file mode 100644 index 00000000000..fd0f1a1eab1 --- /dev/null +++ b/pkg/api/app_settings.go @@ -0,0 +1,59 @@ +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") +} diff --git a/pkg/api/datasources.go b/pkg/api/datasources.go index 04fdca8242a..54959840d03 100644 --- a/pkg/api/datasources.go +++ b/pkg/api/datasources.go @@ -118,18 +118,17 @@ func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) { func GetDataSourcePlugins(c *middleware.Context) { dsList := make(map[string]*plugins.DataSourcePlugin) - orgApps := m.GetAppPluginsQuery{OrgId: c.OrgId} - err := bus.Dispatch(&orgApps) - if err != nil { + if enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId); err != nil { c.JsonApiErr(500, "Failed to get org apps", err) - } - enabledPlugins := plugins.GetEnabledPlugins(orgApps.Result) + return + } else { - for key, value := range enabledPlugins.DataSources { - if !value.BuiltIn { - dsList[key] = value + for key, value := range enabledPlugins.DataSources { + if !value.BuiltIn { + dsList[key] = value + } } - } - c.JSON(200, dsList) + c.JSON(200, dsList) + } } diff --git a/pkg/api/dtos/app_plugin.go b/pkg/api/dtos/app_plugin.go deleted file mode 100644 index 7213c224cf8..00000000000 --- a/pkg/api/dtos/app_plugin.go +++ /dev/null @@ -1,13 +0,0 @@ -package dtos - -import "github.com/grafana/grafana/pkg/plugins" - -type AppPlugin struct { - Name string `json:"name"` - Type string `json:"type"` - Enabled bool `json:"enabled"` - Pinned bool `json:"pinned"` - Module string `json:"module"` - Info *plugins.PluginInfo `json:"info"` - JsonData map[string]interface{} `json:"jsonData"` -} diff --git a/pkg/api/dtos/apps.go b/pkg/api/dtos/apps.go new file mode 100644 index 00000000000..2db2879f5f7 --- /dev/null +++ b/pkg/api/dtos/apps.go @@ -0,0 +1,31 @@ +package dtos + +import ( + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/plugins" +) + +type AppSettings struct { + Name string `json:"name"` + AppId string `json:"appId"` + Enabled bool `json:"enabled"` + Pinned bool `json:"pinned"` + Info *plugins.PluginInfo `json:"info"` + 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, + } + + if data != nil { + dto.Enabled = data.Enabled + dto.Pinned = data.Pinned + dto.Info = &def.Info + } + + return dto +} diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 486d59608ba..0f9cdee02a9 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -29,14 +29,11 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro datasources := make(map[string]interface{}) var defaultDatasource string - orgApps := m.GetAppPluginsQuery{OrgId: c.OrgId} - err := bus.Dispatch(&orgApps) + enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId) if err != nil { return nil, err } - enabledPlugins := plugins.GetEnabledPlugins(orgApps.Result) - for _, ds := range orgDataSources { url := ds.Url diff --git a/pkg/api/index.go b/pkg/api/index.go index 3a56a7f1205..bbe0c6565a8 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -2,7 +2,6 @@ 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" @@ -69,14 +68,11 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { }) } - orgApps := m.GetAppPluginsQuery{OrgId: c.OrgId} - err = bus.Dispatch(&orgApps) + enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId) if err != nil { return nil, err } - enabledPlugins := plugins.GetEnabledPlugins(orgApps.Result) - for _, plugin := range enabledPlugins.Apps { if plugin.Module != "" { data.PluginModules = append(data.PluginModules, plugin.Module) diff --git a/pkg/models/app_plugin.go b/pkg/models/app_settings.go similarity index 64% rename from pkg/models/app_plugin.go rename to pkg/models/app_settings.go index 3676d85ab01..558946d0277 100644 --- a/pkg/models/app_plugin.go +++ b/pkg/models/app_settings.go @@ -2,9 +2,9 @@ package models import "time" -type AppPlugin struct { +type AppSettings struct { Id int64 - Type string + AppId string OrgId int64 Enabled bool Pinned bool @@ -18,19 +18,18 @@ type AppPlugin struct { // COMMANDS // Also acts as api DTO -type UpdateAppPluginCmd struct { - Type string `json:"type" binding:"Required"` +type UpdateAppSettingsCmd struct { Enabled bool `json:"enabled"` Pinned bool `json:"pinned"` JsonData map[string]interface{} `json:"jsonData"` - Id int64 `json:"-"` - OrgId int64 `json:"-"` + AppId string `json:"-"` + OrgId int64 `json:"-"` } // --------------------- // QUERIES -type GetAppPluginsQuery struct { +type GetAppSettingsQuery struct { OrgId int64 - Result []*AppPlugin + Result []*AppSettings } diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 4626ad8df15..1b945141f6a 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -13,7 +13,6 @@ import ( "text/template" "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) @@ -180,78 +179,3 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error { return loader.Load(jsonParser, currentDir) } - -func GetEnabledPlugins(orgApps []*models.AppPlugin) EnabledPlugins { - enabledPlugins := NewEnabledPlugins() - - orgAppsMap := make(map[string]*models.AppPlugin) - for _, orgApp := range orgApps { - orgAppsMap[orgApp.Type] = orgApp - } - seenPanels := make(map[string]bool) - seenApi := make(map[string]bool) - - for appType, installedApp := range Apps { - var app AppPlugin - app = *installedApp - - // check if the app is stored in the DB for this org and if so, use the - // state stored there. - if b, ok := orgAppsMap[appType]; ok { - app.Enabled = b.Enabled - app.Pinned = b.Pinned - } - - // if app.Enabled { - // for _, d := range app.DatasourcePlugins { - // if ds, ok := DataSources[d]; ok { - // enabledPlugins.DataSourcePlugins[d] = ds - // } - // } - // for _, p := range app.PanelPlugins { - // if panel, ok := Panels[p]; ok { - // if _, ok := seenPanels[p]; !ok { - // seenPanels[p] = true - // enabledPlugins.PanelPlugins = append(enabledPlugins.PanelPlugins, panel) - // } - // } - // } - // for _, a := range app.ApiPlugins { - // if api, ok := ApiPlugins[a]; ok { - // if _, ok := seenApi[a]; !ok { - // seenApi[a] = true - // enabledPlugins.ApiPlugins = append(enabledPlugins.ApiPlugins, api) - // } - // } - // } - // enabledPlugins.AppPlugins = append(enabledPlugins.AppPlugins, &app) - // } - } - - // add all plugins that are not part of an App. - for d, installedDs := range DataSources { - if installedDs.App == "" { - enabledPlugins.DataSources[d] = installedDs - } - } - - for p, panel := range Panels { - if panel.App == "" { - if _, ok := seenPanels[p]; !ok { - seenPanels[p] = true - 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) - } - } - } - - return enabledPlugins -} diff --git a/pkg/plugins/queries.go b/pkg/plugins/queries.go new file mode 100644 index 00000000000..4a7d5294128 --- /dev/null +++ b/pkg/plugins/queries.go @@ -0,0 +1,96 @@ +package plugins + +import ( + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" +) + +func GetOrgAppSettings(orgId int64) (map[string]*m.AppSettings, error) { + query := m.GetAppSettingsQuery{OrgId: orgId} + + if err := bus.Dispatch(&query); err != nil { + return nil, err + } + + orgAppsMap := make(map[string]*m.AppSettings) + for _, orgApp := range query.Result { + orgAppsMap[orgApp.AppId] = orgApp + } + + return orgAppsMap, nil +} + +func GetEnabledPlugins(orgId int64) (*EnabledPlugins, error) { + enabledPlugins := NewEnabledPlugins() + orgApps, err := GetOrgAppSettings(orgId) + if err != nil { + return nil, err + } + + seenPanels := make(map[string]bool) + seenApi := make(map[string]bool) + + for appType, installedApp := range Apps { + var app AppPlugin + app = *installedApp + + // check if the app is stored in the DB for this org and if so, use the + // state stored there. + if b, ok := orgApps[appType]; ok { + app.Enabled = b.Enabled + app.Pinned = b.Pinned + } + + // if app.Enabled { + // for _, d := range app.DatasourcePlugins { + // if ds, ok := DataSources[d]; ok { + // enabledPlugins.DataSourcePlugins[d] = ds + // } + // } + // for _, p := range app.PanelPlugins { + // if panel, ok := Panels[p]; ok { + // if _, ok := seenPanels[p]; !ok { + // seenPanels[p] = true + // enabledPlugins.PanelPlugins = append(enabledPlugins.PanelPlugins, panel) + // } + // } + // } + // for _, a := range app.ApiPlugins { + // if api, ok := ApiPlugins[a]; ok { + // if _, ok := seenApi[a]; !ok { + // seenApi[a] = true + // enabledPlugins.ApiPlugins = append(enabledPlugins.ApiPlugins, api) + // } + // } + // } + // enabledPlugins.AppPlugins = append(enabledPlugins.AppPlugins, &app) + // } + } + + // add all plugins that are not part of an App. + for d, installedDs := range DataSources { + if installedDs.App == "" { + enabledPlugins.DataSources[d] = installedDs + } + } + + for p, panel := range Panels { + if panel.App == "" { + if _, ok := seenPanels[p]; !ok { + seenPanels[p] = true + 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) + } + } + } + + return &enabledPlugins, nil +} diff --git a/pkg/services/sqlstore/app_plugin.go b/pkg/services/sqlstore/app_settings.go similarity index 64% rename from pkg/services/sqlstore/app_plugin.go rename to pkg/services/sqlstore/app_settings.go index fd0c2bc7be1..e9bfbeaa73b 100644 --- a/pkg/services/sqlstore/app_plugin.go +++ b/pkg/services/sqlstore/app_settings.go @@ -8,27 +8,27 @@ import ( ) func init() { - bus.AddHandler("sql", GetAppPlugins) - bus.AddHandler("sql", UpdateAppPlugin) + bus.AddHandler("sql", GetAppSettings) + bus.AddHandler("sql", UpdateAppSettings) } -func GetAppPlugins(query *m.GetAppPluginsQuery) error { +func GetAppSettings(query *m.GetAppSettingsQuery) error { sess := x.Where("org_id=?", query.OrgId) - query.Result = make([]*m.AppPlugin, 0) + query.Result = make([]*m.AppSettings, 0) return sess.Find(&query.Result) } -func UpdateAppPlugin(cmd *m.UpdateAppPluginCmd) error { +func UpdateAppSettings(cmd *m.UpdateAppSettingsCmd) error { return inTransaction2(func(sess *session) error { - var app m.AppPlugin + var app m.AppSettings - exists, err := sess.Where("org_id=? and type=?", cmd.OrgId, cmd.Type).Get(&app) + 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.AppPlugin{ - Type: cmd.Type, + app = m.AppSettings{ + AppId: cmd.AppId, OrgId: cmd.OrgId, Enabled: cmd.Enabled, Pinned: cmd.Pinned, diff --git a/pkg/services/sqlstore/migrations/app_plugin.go b/pkg/services/sqlstore/migrations/app_settings.go similarity index 62% rename from pkg/services/sqlstore/migrations/app_plugin.go rename to pkg/services/sqlstore/migrations/app_settings.go index 7a1e67cf191..437debbe95b 100644 --- a/pkg/services/sqlstore/migrations/app_plugin.go +++ b/pkg/services/sqlstore/migrations/app_settings.go @@ -2,14 +2,14 @@ package migrations import . "github.com/grafana/grafana/pkg/services/sqlstore/migrator" -func addAppPluginMigration(mg *Migrator) { +func addAppSettingsMigration(mg *Migrator) { - var appPluginV2 = Table{ - Name: "app_plugin", + appSettingsV1 := Table{ + Name: "app_settings", Columns: []*Column{ {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, {Name: "org_id", Type: DB_BigInt, Nullable: true}, - {Name: "type", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "app_id", Type: DB_NVarchar, Length: 255, Nullable: false}, {Name: "enabled", Type: DB_Bool, Nullable: false}, {Name: "pinned", Type: DB_Bool, Nullable: false}, {Name: "json_data", Type: DB_Text, Nullable: true}, @@ -17,12 +17,12 @@ func addAppPluginMigration(mg *Migrator) { {Name: "updated", Type: DB_DateTime, Nullable: false}, }, Indices: []*Index{ - {Cols: []string{"org_id", "type"}, Type: UniqueIndex}, + {Cols: []string{"org_id", "app_id"}, Type: UniqueIndex}, }, } - mg.AddMigration("create app_plugin table v2", NewAddTableMigration(appPluginV2)) + mg.AddMigration("create app_settings table v1", NewAddTableMigration(appSettingsV1)) //------- indexes ------------------ - addTableIndicesMigrations(mg, "v2", appPluginV2) + addTableIndicesMigrations(mg, "v3", appSettingsV1) } diff --git a/pkg/services/sqlstore/migrations/migrations.go b/pkg/services/sqlstore/migrations/migrations.go index a6f3eacffc3..a2baac7be5e 100644 --- a/pkg/services/sqlstore/migrations/migrations.go +++ b/pkg/services/sqlstore/migrations/migrations.go @@ -18,7 +18,7 @@ func AddMigrations(mg *Migrator) { addApiKeyMigrations(mg) addDashboardSnapshotMigrations(mg) addQuotaMigration(mg) - addAppPluginMigration(mg) + addAppSettingsMigration(mg) addSessionMigration(mg) } diff --git a/public/app/core/routes/all.js b/public/app/core/routes/all.js index 0d4741c9e47..cc4d73ef708 100644 --- a/public/app/core/routes/all.js +++ b/public/app/core/routes/all.js @@ -138,7 +138,7 @@ define([ controllerAs: 'ctrl', resolve: loadAppsBundle, }) - .when('/apps/edit/:type', { + .when('/apps/edit/:appId', { templateUrl: 'app/features/apps/partials/edit.html', controller: 'AppEditCtrl', controllerAs: 'ctrl', diff --git a/public/app/features/apps/all.ts b/public/app/features/apps/all.ts index 005c0796493..fcdd27dff4d 100644 --- a/public/app/features/apps/all.ts +++ b/public/app/features/apps/all.ts @@ -1,3 +1,2 @@ import './edit_ctrl'; import './list_ctrl'; -import './app_srv'; diff --git a/public/app/features/apps/app_srv.ts b/public/app/features/apps/app_srv.ts index 0f937e601bc..18c6979b388 100644 --- a/public/app/features/apps/app_srv.ts +++ b/public/app/features/apps/app_srv.ts @@ -15,9 +15,6 @@ export class AppSrv { } get(type) { - if (this.apps[type]) { - return this.$q.when(this.apps[type]); - } return this.getAll().then(() => { return this.apps[type]; }); @@ -38,7 +35,7 @@ export class AppSrv { update(app) { return this.backendSrv.post('api/org/apps', app).then(resp => { - this.apps[app.type] = app; + }); } } diff --git a/public/app/features/apps/edit_ctrl.ts b/public/app/features/apps/edit_ctrl.ts index 7c4553ac332..fe77c0a6797 100644 --- a/public/app/features/apps/edit_ctrl.ts +++ b/public/app/features/apps/edit_ctrl.ts @@ -8,20 +8,36 @@ export class AppEditCtrl { appModel: any; /** @ngInject */ - constructor(private appSrv: any, private $routeParams: any) {} + constructor(private backendSrv: any, private $routeParams: any) {} init() { this.appModel = {}; - this.appSrv.get(this.$routeParams.type).then(result => { - this.appModel = _.clone(result); + this.backendSrv.get(`/api/org/apps/${this.$routeParams.appId}/settings`).then(result => { + this.appModel = result; }); } - update() { - this.appSrv.update(this.appModel).then(function() { - window.location.href = config.appSubUrl + "org/apps"; + update(options) { + var updateCmd = _.extend({ + appId: this.appModel.appId, + orgId: this.appModel.orgId, + enabled: this.appModel.enabled, + pinned: this.appModel.pinned, + jsonData: this.appModel.jsonData, + }, options); + + this.backendSrv.post(`/api/org/apps/${this.$routeParams.appId}/settings`, updateCmd).then(function() { + window.location.href = window.location.href; }); } + + toggleEnabled() { + this.update({enabled: this.appModel.enabled}); + } + + togglePinned() { + this.update({pinned: this.appModel.pinned}); + } } angular.module('grafana.controllers').controller('AppEditCtrl', AppEditCtrl); diff --git a/public/app/features/apps/list_ctrl.ts b/public/app/features/apps/list_ctrl.ts index 7d89a3baffe..3f195536ae4 100644 --- a/public/app/features/apps/list_ctrl.ts +++ b/public/app/features/apps/list_ctrl.ts @@ -7,11 +7,11 @@ export class AppListCtrl { apps: any[]; /** @ngInject */ - constructor(private appSrv: any) {} + constructor(private backendSrv: any) {} init() { - this.appSrv.getAll().then(result => { - this.apps = result; + this.backendSrv.get('api/org/apps').then(apps => { + this.apps = apps; }); } } diff --git a/public/app/features/apps/partials/edit.html b/public/app/features/apps/partials/edit.html index 3dd8e24d593..da029b51b8c 100644 --- a/public/app/features/apps/partials/edit.html +++ b/public/app/features/apps/partials/edit.html @@ -1,7 +1,7 @@ @@ -25,10 +25,12 @@ {{ctrl.appModel.info.description}} +

- - + +       +
diff --git a/public/app/features/apps/partials/list.html b/public/app/features/apps/partials/list.html index 37897546eed..c682d2fc8ef 100644 --- a/public/app/features/apps/partials/list.html +++ b/public/app/features/apps/partials/list.html @@ -15,10 +15,13 @@