mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(plugins): progress on plugin details page, # 4275
This commit is contained in:
parent
1ff428087e
commit
135679096b
@ -35,7 +35,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"grafanaVersion": "2.6.x",
|
"grafanaVersion": "3.x.x",
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{"type": "datasource", "id": "graphite", "name": "Graphite", "version": "1.0.0"},
|
{"type": "datasource", "id": "graphite", "name": "Graphite", "version": "1.0.0"},
|
||||||
{"type": "panel", "id": "graph", "name": "Graph", "version": "1.0.0"}
|
{"type": "panel", "id": "graph", "name": "Graph", "version": "1.0.0"}
|
||||||
|
@ -3,17 +3,18 @@ package dtos
|
|||||||
import "github.com/grafana/grafana/pkg/plugins"
|
import "github.com/grafana/grafana/pkg/plugins"
|
||||||
|
|
||||||
type PluginSetting struct {
|
type PluginSetting struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
PluginId string `json:"pluginId"`
|
PluginId string `json:"pluginId"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
Pinned bool `json:"pinned"`
|
Pinned bool `json:"pinned"`
|
||||||
Module string `json:"module"`
|
Module string `json:"module"`
|
||||||
BaseUrl string `json:"baseUrl"`
|
BaseUrl string `json:"baseUrl"`
|
||||||
Info *plugins.PluginInfo `json:"info"`
|
Info *plugins.PluginInfo `json:"info"`
|
||||||
Pages []*plugins.AppPluginPage `json:"pages"`
|
Pages []*plugins.AppPluginPage `json:"pages"`
|
||||||
Includes []*plugins.AppIncludeInfo `json:"includes"`
|
Includes []*plugins.AppIncludeInfo `json:"includes"`
|
||||||
JsonData map[string]interface{} `json:"jsonData"`
|
Dependencies *plugins.PluginDependencies `json:"dependencies"`
|
||||||
|
JsonData map[string]interface{} `json:"jsonData"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PluginListItem struct {
|
type PluginListItem struct {
|
||||||
|
@ -42,10 +42,11 @@ func GetPluginSettingById(c *middleware.Context) Response {
|
|||||||
return ApiError(404, "Plugin not found, no installed plugin with that id", nil)
|
return ApiError(404, "Plugin not found, no installed plugin with that id", nil)
|
||||||
} else {
|
} else {
|
||||||
dto := &dtos.PluginSetting{
|
dto := &dtos.PluginSetting{
|
||||||
Type: def.Type,
|
Type: def.Type,
|
||||||
PluginId: def.Id,
|
PluginId: def.Id,
|
||||||
Name: def.Name,
|
Name: def.Name,
|
||||||
Info: &def.Info,
|
Info: &def.Info,
|
||||||
|
Dependencies: &def.Dependencies,
|
||||||
}
|
}
|
||||||
|
|
||||||
if app, exists := plugins.Apps[pluginId]; exists {
|
if app, exists := plugins.Apps[pluginId]; exists {
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/social"
|
"github.com/grafana/grafana/pkg/social"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "master"
|
var version = "3.0.0-pre1"
|
||||||
var commit = "NA"
|
var commit = "NA"
|
||||||
var buildstamp string
|
var buildstamp string
|
||||||
var build_date string
|
var build_date string
|
||||||
|
@ -28,8 +28,8 @@ func (fp *FrontendPluginBase) initFrontendPlugin() {
|
|||||||
|
|
||||||
fp.handleModuleDefaults()
|
fp.handleModuleDefaults()
|
||||||
|
|
||||||
fp.Info.Logos.Small = evalRelativePluginUrlPath(fp.Info.Logos.Small, fp.Id)
|
fp.Info.Logos.Small = evalRelativePluginUrlPath(fp.Info.Logos.Small, fp.BaseUrl)
|
||||||
fp.Info.Logos.Large = evalRelativePluginUrlPath(fp.Info.Logos.Large, fp.Id)
|
fp.Info.Logos.Large = evalRelativePluginUrlPath(fp.Info.Logos.Large, fp.BaseUrl)
|
||||||
|
|
||||||
for i := 0; i < len(fp.Info.Screenshots); i++ {
|
for i := 0; i < len(fp.Info.Screenshots); i++ {
|
||||||
fp.Info.Screenshots[i].Path = evalRelativePluginUrlPath(fp.Info.Screenshots[i].Path, fp.Id)
|
fp.Info.Screenshots[i].Path = evalRelativePluginUrlPath(fp.Info.Screenshots[i].Path, fp.Id)
|
||||||
@ -55,7 +55,7 @@ func (fp *FrontendPluginBase) handleModuleDefaults() {
|
|||||||
fp.BaseUrl = path.Join("public/app/plugins", fp.Type, fp.Id)
|
fp.BaseUrl = path.Join("public/app/plugins", fp.Type, fp.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalRelativePluginUrlPath(pathStr string, pluginId string) string {
|
func evalRelativePluginUrlPath(pathStr string, baseUrl string) string {
|
||||||
if pathStr == "" {
|
if pathStr == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -64,5 +64,5 @@ func evalRelativePluginUrlPath(pathStr string, pluginId string) string {
|
|||||||
if u.IsAbs() {
|
if u.IsAbs() {
|
||||||
return pathStr
|
return pathStr
|
||||||
}
|
}
|
||||||
return path.Join("public/plugins", pluginId, pathStr)
|
return path.Join(baseUrl, pathStr)
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,11 @@ type PluginLoader interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PluginBase struct {
|
type PluginBase struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Info PluginInfo `json:"info"`
|
Info PluginInfo `json:"info"`
|
||||||
|
Dependencies PluginDependencies `json:"dependencies"`
|
||||||
|
|
||||||
IncludedInAppId string `json:"-"`
|
IncludedInAppId string `json:"-"`
|
||||||
PluginDir string `json:"-"`
|
PluginDir string `json:"-"`
|
||||||
@ -37,6 +38,18 @@ func (pb *PluginBase) registerPlugin(pluginDir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PluginDependencies struct {
|
||||||
|
GrafanaVersion string `json:"grafanaVersion"`
|
||||||
|
Plugins []PluginDependencyItem `json:"plugins"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginDependencyItem struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
type PluginInfo struct {
|
type PluginInfo struct {
|
||||||
Author PluginInfoLink `json:"author"`
|
Author PluginInfoLink `json:"author"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
<div class="tabbed-view-body">
|
<div class="tabbed-view-body">
|
||||||
<div ng-if="editor.index == 0">
|
<div ng-if="editor.index == 0">
|
||||||
|
|
||||||
<h5 class="section-heading">Dashboard Detail</h5>
|
|
||||||
<div class="gf-form-group">
|
<div class="gf-form-group">
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-7">Title</label>
|
<label class="gf-form-label width-7">Title</label>
|
||||||
|
@ -5,6 +5,7 @@ import _ from 'lodash';
|
|||||||
|
|
||||||
export class PluginEditCtrl {
|
export class PluginEditCtrl {
|
||||||
model: any;
|
model: any;
|
||||||
|
pluginIcon: string;
|
||||||
pluginId: any;
|
pluginId: any;
|
||||||
includedPanels: any;
|
includedPanels: any;
|
||||||
includedDatasources: any;
|
includedDatasources: any;
|
||||||
@ -22,9 +23,22 @@ export class PluginEditCtrl {
|
|||||||
this.model = result;
|
this.model = result;
|
||||||
this.includedPanels = _.where(result.includes, {type: 'panel'});
|
this.includedPanels = _.where(result.includes, {type: 'panel'});
|
||||||
this.includedDatasources = _.where(result.includes, {type: 'datasource'});
|
this.includedDatasources = _.where(result.includes, {type: 'datasource'});
|
||||||
|
this.pluginIcon = this.getPluginIcon(this.model.type);
|
||||||
|
|
||||||
|
this.model.dependencies.plugins.forEach(plug => {
|
||||||
|
plug.icon = this.getPluginIcon(plug.type);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPluginIcon(type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'datasource': return 'icon-gf icon-gf-datasources';
|
||||||
|
case 'panel': return 'icon-gf icon-gf-panel';
|
||||||
|
case 'app': return 'icon-gf icon-gf-apps';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
var chain = Promise.resolve();
|
var chain = Promise.resolve();
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -53,7 +67,7 @@ export class PluginEditCtrl {
|
|||||||
|
|
||||||
// if set, performt he postUpdate hook. If a promise is returned it will block
|
// if set, performt he postUpdate hook. If a promise is returned it will block
|
||||||
// the final step of the update procedure (reloading the page) until the promise
|
// the final step of the update procedure (reloading the page) until the promise
|
||||||
// resolves. If the promise is rejected the page will not be reloaded.
|
// resolves. If the promise is rejected the page will not be reloaded.
|
||||||
if (this.postUpdateHook != null) {
|
if (this.postUpdateHook != null) {
|
||||||
chain = chain.then(function() {
|
chain = chain.then(function() {
|
||||||
return Promise.resolve(this.postUpdateHook());
|
return Promise.resolve(this.postUpdateHook());
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<navbar title="Plugins" title-url="plugins" icon="icon-gf icon-gf-apps">
|
<navbar title="Plugins" title-url="plugins" icon="icon-gf icon-gf-apps">
|
||||||
<a href="plugins/apps" class="navbar-page-btn">
|
<a href="plugins/apps" class="navbar-page-btn">
|
||||||
<i class="fa fa-chevron-right"></i>
|
Plugin details
|
||||||
Apps
|
|
||||||
</a>
|
</a>
|
||||||
</navbar>
|
</navbar>
|
||||||
|
|
||||||
@ -15,7 +14,7 @@
|
|||||||
<div class="plugin-header-author">By {{ctrl.model.info.author.name}}</div>
|
<div class="plugin-header-author">By {{ctrl.model.info.author.name}}</div>
|
||||||
<div class="plugin-header-stamps">
|
<div class="plugin-header-stamps">
|
||||||
<span class="plugin-header-stamps-type">
|
<span class="plugin-header-stamps-type">
|
||||||
<i class="icon-gf icon-gf-apps"></i> {{ctrl.model.type}}
|
<i class="{{ctrl.pluginIcon}}"></i> {{ctrl.model.type}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -59,7 +58,7 @@
|
|||||||
<aside class="page-sidebar">
|
<aside class="page-sidebar">
|
||||||
<section class="page-sidebar-section">
|
<section class="page-sidebar-section">
|
||||||
<h4>Version</h4>
|
<h4>Version</h4>
|
||||||
<span>1.0.1</span>
|
<span>{{ctrl.model.info.version}}</span>
|
||||||
</section>
|
</section>
|
||||||
<section class="page-sidebar-section" ng-show="ctrl.model.type === 'app'">
|
<section class="page-sidebar-section" ng-show="ctrl.model.type === 'app'">
|
||||||
<h5>Includes</h4>
|
<h5>Includes</h4>
|
||||||
@ -78,7 +77,30 @@
|
|||||||
</section>
|
</section>
|
||||||
<section class="page-sidebar-section">
|
<section class="page-sidebar-section">
|
||||||
<h5>Dependencies</h4>
|
<h5>Dependencies</h4>
|
||||||
<span>TODO</span>
|
<ul class="ui-list">
|
||||||
|
<li>
|
||||||
|
<span class="plugin-dependency-icon">
|
||||||
|
<img src="public/img/grafana_icon.svg"></img>
|
||||||
|
</span>
|
||||||
|
<span class="plugin-dependency-name">
|
||||||
|
Grafana
|
||||||
|
</span>
|
||||||
|
<span class="plugin-dependency-version">
|
||||||
|
{{ctrl.model.dependencies.grafanaVersion}}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li ng-repeat="plugDep in ctrl.model.dependencies.plugins">
|
||||||
|
<span class="plugin-dependency-icon">
|
||||||
|
<i class="{{plugDep.icon}}"></i>
|
||||||
|
</span>
|
||||||
|
<span class="plugin-dependency-name">
|
||||||
|
{{plugDep.name}}
|
||||||
|
</span>
|
||||||
|
<span class="plugin-dependency-version">
|
||||||
|
{{plugDep.version}}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section class="page-sidebar-section">
|
<section class="page-sidebar-section">
|
||||||
<h5>Links</h4>
|
<h5>Links</h4>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<div class="modal-content text-center">
|
<div class="modal-content text-center">
|
||||||
|
|
||||||
<div class="confirm-modal-title">
|
<div class="confirm-modal-text">
|
||||||
What do you want to do?
|
What do you want to do?
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
BIN
public/app/plugins/datasource/elasticsearch/img/logo_large.png
Normal file
BIN
public/app/plugins/datasource/elasticsearch/img/logo_large.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
@ -3,7 +3,23 @@
|
|||||||
"name": "Elasticsearch",
|
"name": "Elasticsearch",
|
||||||
"id": "elasticsearch",
|
"id": "elasticsearch",
|
||||||
|
|
||||||
"defaultMatchFormat": "lucene",
|
"info": {
|
||||||
|
"description": "Elasticsearch Data Source for Grafana",
|
||||||
|
"author": {
|
||||||
|
"name": "Grafana Core",
|
||||||
|
"url": "http://grafana.org"
|
||||||
|
},
|
||||||
|
"keywords": ["elasticsearch"],
|
||||||
|
"logos": {
|
||||||
|
"small": "img/logo_large.png",
|
||||||
|
"large": "img/logo_large.png"
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{"name": "elastic.co", "url": "https://www.elastic.co/products/elasticsearch"}
|
||||||
|
],
|
||||||
|
"version": "3.0.0"
|
||||||
|
},
|
||||||
|
|
||||||
"annotations": true,
|
"annotations": true,
|
||||||
"metrics": true
|
"metrics": true
|
||||||
}
|
}
|
||||||
|
@ -84,11 +84,9 @@
|
|||||||
h4 {
|
h4 {
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
font-weight: $font-weight-semi-bold;
|
font-weight: $font-weight-semi-bold;
|
||||||
color: $text-color-strong;
|
|
||||||
}
|
}
|
||||||
h5 {
|
h5 {
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
color: $text-color-weak;
|
|
||||||
font-weight: $font-weight-semi-bold;
|
font-weight: $font-weight-semi-bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.plugin-header-stamps-type {
|
.plugin-header-stamps-type {
|
||||||
color: $link-color-disabled;
|
color: $headings-color-disabled;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.plugin-dependency-icon {
|
||||||
|
img {
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// .app-edit-logo-box {
|
// .app-edit-logo-box {
|
||||||
// padding: 1.2rem;
|
// padding: 1.2rem;
|
||||||
// background: $panel-bg;
|
// background: $panel-bg;
|
||||||
|
Loading…
Reference in New Issue
Block a user