mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
App Plugins: support react pages and tabs (#16586)
This commit is contained in:
102
public/app/plugins/app/example-app/ExampleRootPage.tsx
Normal file
102
public/app/plugins/app/example-app/ExampleRootPage.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Types
|
||||
import { AppRootProps, NavModelItem } from '@grafana/ui';
|
||||
|
||||
interface Props extends AppRootProps {}
|
||||
|
||||
const TAB_ID_A = 'A';
|
||||
const TAB_ID_B = 'B';
|
||||
const TAB_ID_C = 'C';
|
||||
|
||||
export class ExampleRootPage extends PureComponent<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateNav();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
if (this.props.query !== prevProps.query) {
|
||||
if (this.props.query.tab !== prevProps.query.tab) {
|
||||
this.updateNav();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateNav() {
|
||||
const { path, onNavChanged, query, meta } = this.props;
|
||||
|
||||
const tabs: NavModelItem[] = [];
|
||||
tabs.push({
|
||||
text: 'Tab A',
|
||||
icon: 'fa fa-fw fa-file-text-o',
|
||||
url: path + '?tab=' + TAB_ID_A,
|
||||
id: TAB_ID_A,
|
||||
});
|
||||
tabs.push({
|
||||
text: 'Tab B',
|
||||
icon: 'fa fa-fw fa-file-text-o',
|
||||
url: path + '?tab=' + TAB_ID_B,
|
||||
id: TAB_ID_B,
|
||||
});
|
||||
tabs.push({
|
||||
text: 'Tab C',
|
||||
icon: 'fa fa-fw fa-file-text-o',
|
||||
url: path + '?tab=' + TAB_ID_C,
|
||||
id: TAB_ID_C,
|
||||
});
|
||||
|
||||
// Set the active tab
|
||||
let found = false;
|
||||
const selected = query.tab || TAB_ID_B;
|
||||
for (const tab of tabs) {
|
||||
tab.active = !found && selected === tab.id;
|
||||
if (tab.active) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
tabs[0].active = true;
|
||||
}
|
||||
|
||||
const node = {
|
||||
text: 'This is the Page title',
|
||||
img: meta.info.logos.large,
|
||||
subTitle: 'subtitle here',
|
||||
url: path,
|
||||
children: tabs,
|
||||
};
|
||||
|
||||
// Update the page header
|
||||
onNavChanged({
|
||||
node: node,
|
||||
main: node,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { path, query } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
QUERY: <pre>{JSON.stringify(query)}</pre>
|
||||
<br />
|
||||
<ul>
|
||||
<li>
|
||||
<a href={path + '?x=1'}>111</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={path + '?x=AAA'}>AAA</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={path + '?x=1&y=2&y=3'}>ZZZ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
25
public/app/plugins/app/example-app/config/ExampleTab1.tsx
Normal file
25
public/app/plugins/app/example-app/config/ExampleTab1.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Types
|
||||
import { PluginConfigTabProps, AppPluginMeta } from '@grafana/ui';
|
||||
|
||||
interface Props extends PluginConfigTabProps<AppPluginMeta> {}
|
||||
|
||||
export class ExampleTab1 extends PureComponent<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { query } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
11111111111111111111111111111111
|
||||
<pre>{JSON.stringify(query)}</pre>
|
||||
11111111111111111111111111111111
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
25
public/app/plugins/app/example-app/config/ExampleTab2.tsx
Normal file
25
public/app/plugins/app/example-app/config/ExampleTab2.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
// Libraries
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Types
|
||||
import { PluginConfigTabProps, AppPluginMeta } from '@grafana/ui';
|
||||
|
||||
interface Props extends PluginConfigTabProps<AppPluginMeta> {}
|
||||
|
||||
export class ExampleTab2 extends PureComponent<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { query } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
22222222222222222222222222222222
|
||||
<pre>{JSON.stringify(query)}</pre>
|
||||
22222222222222222222222222222222
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
110
public/app/plugins/app/example-app/dashboards/stats.json
Normal file
110
public/app/plugins/app/example-app/dashboards/stats.json
Normal file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"__inputs": [],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "6.2.0-pre"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "singlestat2",
|
||||
"name": "Singlestat (react)",
|
||||
"version": ""
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 4,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"orientation": "auto",
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": true
|
||||
},
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"index": 1,
|
||||
"value": 80
|
||||
}
|
||||
],
|
||||
"valueMappings": [],
|
||||
"valueOptions": {
|
||||
"decimals": null,
|
||||
"prefix": "",
|
||||
"stat": "mean",
|
||||
"suffix": "",
|
||||
"unit": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "6.2.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk_table",
|
||||
"stringInput": ""
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "random_walk_table",
|
||||
"stringInput": ""
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"type": "singlestat2"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 18,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
|
||||
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
||||
},
|
||||
"timezone": "",
|
||||
"title": "stats",
|
||||
"uid": "YeBxHjzWz",
|
||||
"version": 1
|
||||
}
|
||||
83
public/app/plugins/app/example-app/dashboards/streaming.json
Normal file
83
public/app/plugins/app/example-app/dashboards/streaming.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"__inputs": [],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "6.2.0-pre"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "graph2",
|
||||
"name": "React Graph",
|
||||
"version": ""
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"description": "",
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"links": [],
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "streaming_client",
|
||||
"stream": {
|
||||
"noise": 10,
|
||||
"speed": 100,
|
||||
"spread": 20,
|
||||
"type": "signal"
|
||||
},
|
||||
"stringInput": ""
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Simple dummy streaming example",
|
||||
"type": "graph2"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 18,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-1m",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
|
||||
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
||||
},
|
||||
"timezone": "",
|
||||
"title": "simple streaming",
|
||||
"uid": "TbbEZjzWz",
|
||||
"version": 1
|
||||
}
|
||||
@@ -1,9 +1,28 @@
|
||||
// Angular pages
|
||||
import { ExampleConfigCtrl } from './legacy/config';
|
||||
import { AngularExamplePageCtrl } from './legacy/angular_example_page';
|
||||
import { AppPlugin } from '@grafana/ui';
|
||||
import { ExampleTab1 } from './config/ExampleTab1';
|
||||
import { ExampleTab2 } from './config/ExampleTab2';
|
||||
import { ExampleRootPage } from './ExampleRootPage';
|
||||
|
||||
// Legacy exports just for testing
|
||||
export {
|
||||
ExampleConfigCtrl as ConfigCtrl,
|
||||
// Must match `pages.component` in plugin.json
|
||||
AngularExamplePageCtrl,
|
||||
AngularExamplePageCtrl, // Must match `pages.component` in plugin.json
|
||||
};
|
||||
|
||||
export const plugin = new AppPlugin()
|
||||
.setRootPage(ExampleRootPage)
|
||||
.addConfigTab({
|
||||
title: 'Tab 1',
|
||||
icon: 'fa fa-info',
|
||||
body: ExampleTab1,
|
||||
id: 'tab1',
|
||||
})
|
||||
.addConfigTab({
|
||||
title: 'Tab 2',
|
||||
icon: 'fa fa-user',
|
||||
body: ExampleTab2,
|
||||
id: 'tab2',
|
||||
});
|
||||
|
||||
@@ -23,6 +23,20 @@
|
||||
"role": "Viewer",
|
||||
"addToNav": true,
|
||||
"defaultNav": true
|
||||
},
|
||||
{
|
||||
"type": "dashboard",
|
||||
"name": "Streaming Example",
|
||||
"path": "dashboards/streaming.json"
|
||||
},
|
||||
{
|
||||
"type": "dashboard",
|
||||
"name": "Lots of Stats",
|
||||
"path": "dashboards/stats.json"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"name": "Anything -- just display?"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user