Plugins: Unifying alpha state & options for all plugins (#16530)

* app pages

* app pages

* workign example

* started alpha support

* remove app stuff

* show warning on alpha/beta panels

* put app back on plugin file

* fix go

* add enum for PluginType and PluginIncludeType

* Refactoring and moving settings to plugins section

fixes #16529
This commit is contained in:
Ryan McKinley
2019-04-12 04:46:42 -07:00
committed by Torkel Ödegaard
parent 30dcf0f6c5
commit 3c21a121eb
18 changed files with 154 additions and 114 deletions

View File

@@ -7,7 +7,7 @@ import { AlertBox } from 'app/core/components/AlertBox/AlertBox';
// Types
import { PanelPlugin, AppNotificationSeverity } from 'app/types';
import { PanelProps, ReactPanelPlugin } from '@grafana/ui';
import { PanelProps, ReactPanelPlugin, PluginType } from '@grafana/ui';
interface Props {
pluginId: string;
@@ -45,6 +45,7 @@ export function getPanelPluginNotFound(id: string): PanelPlugin {
id: id,
name: id,
sort: 100,
type: PluginType.panel,
module: '',
baseUrl: '',
dataFormats: [],

View File

@@ -18,6 +18,7 @@ import { PanelModel } from '../state';
import { DashboardModel } from '../state';
import { PanelPlugin } from 'app/types/plugins';
import { VizPickerSearch } from './VizPickerSearch';
import PluginStateinfo from 'app/features/plugins/PluginStateInfo';
interface Props {
panel: PanelModel;
@@ -238,6 +239,7 @@ export class VisualizationTab extends PureComponent<Props, State> {
onClose={this.onCloseVizPicker}
/>
</FadeIn>
<PluginStateinfo state={plugin.state} />
{this.renderPanelOptions()}
</>
</EditorTabBody>

View File

@@ -24,6 +24,7 @@ import { getRouteParamsId } from 'app/core/selectors/location';
import { NavModel, Plugin, StoreState } from 'app/types/';
import { DataSourceSettings } from '@grafana/ui/src/types/';
import { getDataSourceLoadingNav } from '../state/navModel';
import PluginStateinfo from 'app/features/plugins/PluginStateInfo';
export interface Props {
navModel: NavModel;
@@ -44,11 +45,6 @@ interface State {
testingStatus?: string;
}
enum DataSourceStates {
Alpha = 'alpha',
Beta = 'beta',
}
export class DataSourceSettingsPage extends PureComponent<Props, State> {
constructor(props: Props) {
super(props);
@@ -110,32 +106,6 @@ export class DataSourceSettingsPage extends PureComponent<Props, State> {
return this.props.dataSource.readOnly === true;
}
shouldRenderInfoBox() {
const { state } = this.props.dataSourceMeta;
return state === DataSourceStates.Alpha || state === DataSourceStates.Beta;
}
getInfoText() {
const { dataSourceMeta } = this.props;
switch (dataSourceMeta.state) {
case DataSourceStates.Alpha:
return (
'This plugin is marked as being in alpha state, which means it is in early development phase and updates' +
' will include breaking changes.'
);
case DataSourceStates.Beta:
return (
'This plugin is marked as being in a beta development state. This means it is in currently in active' +
' development and could be missing important features.'
);
}
return null;
}
renderIsReadOnlyMessage() {
return (
<div className="grafana-info-box span8">
@@ -196,7 +166,7 @@ export class DataSourceSettingsPage extends PureComponent<Props, State> {
<div>
<form onSubmit={this.onSubmit}>
{this.isReadOnly() && this.renderIsReadOnlyMessage()}
{this.shouldRenderInfoBox() && <div className="grafana-info-box">{this.getInfoText()}</div>}
<PluginStateinfo state={dataSourceMeta.state} />
<BasicSettings
dataSourceName={dataSource.name}

View File

@@ -11,11 +11,9 @@ exports[`Render should render alpha info text 1`] = `
<form
onSubmit={[Function]}
>
<div
className="grafana-info-box"
>
This plugin is marked as being in alpha state, which means it is in early development phase and updates will include breaking changes.
</div>
<PluginStateinfo
state="alpha"
/>
<BasicSettings
dataSourceName="gdev-cloudwatch"
isDefault={false}
@@ -49,6 +47,7 @@ exports[`Render should render alpha info text 1`] = `
}
dataSourceMeta={
Object {
"baseUrl": "path/to/plugin",
"defaultNavUrl": "some/url",
"enabled": false,
"hasUpdate": false,
@@ -78,11 +77,11 @@ exports[`Render should render alpha info text 1`] = `
"version": "1",
},
"latestVersion": "1",
"module": Object {},
"module": "path/to/module",
"name": "pretty cool plugin 1",
"pinned": false,
"state": "alpha",
"type": "",
"type": "panel",
}
}
onModelChange={[Function]}
@@ -113,11 +112,9 @@ exports[`Render should render beta info text 1`] = `
<form
onSubmit={[Function]}
>
<div
className="grafana-info-box"
>
This plugin is marked as being in a beta development state. This means it is in currently in active development and could be missing important features.
</div>
<PluginStateinfo
state="beta"
/>
<BasicSettings
dataSourceName="gdev-cloudwatch"
isDefault={false}
@@ -151,6 +148,7 @@ exports[`Render should render beta info text 1`] = `
}
dataSourceMeta={
Object {
"baseUrl": "path/to/plugin",
"defaultNavUrl": "some/url",
"enabled": false,
"hasUpdate": false,
@@ -180,11 +178,11 @@ exports[`Render should render beta info text 1`] = `
"version": "1",
},
"latestVersion": "1",
"module": Object {},
"module": "path/to/module",
"name": "pretty cool plugin 1",
"pinned": false,
"state": "beta",
"type": "",
"type": "panel",
}
}
onModelChange={[Function]}
@@ -215,6 +213,7 @@ exports[`Render should render component 1`] = `
<form
onSubmit={[Function]}
>
<PluginStateinfo />
<BasicSettings
dataSourceName="gdev-cloudwatch"
isDefault={false}
@@ -248,6 +247,7 @@ exports[`Render should render component 1`] = `
}
dataSourceMeta={
Object {
"baseUrl": "path/to/plugin",
"defaultNavUrl": "some/url",
"enabled": false,
"hasUpdate": false,
@@ -277,11 +277,10 @@ exports[`Render should render component 1`] = `
"version": "1",
},
"latestVersion": "1",
"module": Object {},
"module": "path/to/module",
"name": "pretty cool plugin 1",
"pinned": false,
"state": "",
"type": "",
"type": "panel",
}
}
onModelChange={[Function]}
@@ -317,6 +316,7 @@ exports[`Render should render is ready only message 1`] = `
>
This datasource was added by config and cannot be modified using the UI. Please contact your server admin to update this datasource.
</div>
<PluginStateinfo />
<BasicSettings
dataSourceName="gdev-cloudwatch"
isDefault={false}
@@ -350,6 +350,7 @@ exports[`Render should render is ready only message 1`] = `
}
dataSourceMeta={
Object {
"baseUrl": "path/to/plugin",
"defaultNavUrl": "some/url",
"enabled": false,
"hasUpdate": false,
@@ -379,11 +380,10 @@ exports[`Render should render is ready only message 1`] = `
"version": "1",
},
"latestVersion": "1",
"module": Object {},
"module": "path/to/module",
"name": "pretty cool plugin 1",
"pinned": false,
"state": "",
"type": "",
"type": "panel",
}
}
onModelChange={[Function]}

View File

@@ -1,5 +1,5 @@
import { NavModel, NavModelItem } from 'app/types';
import { PluginMeta, DataSourceSettings } from '@grafana/ui/src/types';
import { PluginMeta, DataSourceSettings, PluginType } from '@grafana/ui/src/types';
import config from 'app/core/config';
export function buildNavModel(dataSource: DataSourceSettings, pluginMeta: PluginMeta): NavModelItem {
@@ -67,6 +67,7 @@ export function getDataSourceLoadingNav(pageName: string): NavModel {
},
{
id: '1',
type: PluginType.datasource,
name: '',
info: {
author: {
@@ -83,7 +84,7 @@ export function getDataSourceLoadingNav(pageName: string): NavModel {
updated: '',
version: '',
},
includes: [{ type: '', name: '', path: '' }],
includes: [],
module: '',
baseUrl: '',
}

View File

@@ -14,22 +14,22 @@ import {
} from './actions';
import { getMockDataSources, getMockDataSource } from '../__mocks__/dataSourcesMocks';
import { LayoutModes } from 'app/core/components/LayoutSelector/LayoutSelector';
import { DataSourcesState } from 'app/types';
import { PluginMetaInfo } from '@grafana/ui';
import { DataSourcesState, Plugin } from 'app/types';
import { PluginMetaInfo, PluginType } from '@grafana/ui';
const mockPlugin = () => ({
defaultNavUrl: 'defaultNavUrl',
enabled: true,
hasUpdate: true,
id: 'id',
info: {} as PluginMetaInfo,
latestVersion: 'latestVersion',
name: 'name',
pinned: true,
state: 'state',
type: 'type',
module: {},
});
const mockPlugin = () =>
({
defaultNavUrl: 'defaultNavUrl',
enabled: true,
hasUpdate: true,
id: 'id',
info: {} as PluginMetaInfo,
latestVersion: 'latestVersion',
name: 'name',
pinned: true,
type: PluginType.datasource,
module: 'path/to/module',
} as Plugin);
describe('dataSourcesReducer', () => {
describe('when dataSourcesLoaded is dispatched', () => {

View File

@@ -0,0 +1,34 @@
import React, { FC } from 'react';
import { PluginState } from '@grafana/ui';
interface Props {
state?: PluginState;
}
function getPluginStateInfoText(state?: PluginState): string | null {
switch (state) {
case PluginState.alpha:
return (
'This plugin is marked as being in alpha state, which means it is in early development phase and updates' +
' will include breaking changes.'
);
case PluginState.beta:
return (
'This plugin is marked as being in a beta development state. This means it is in currently in active' +
' development and could be missing important features.'
);
}
return null;
}
const PluginStateinfo: FC<Props> = props => {
const text = getPluginStateInfoText(props.state);
if (!text) {
return null;
}
return <div className="grafana-info-box">{text}</div>;
};
export default PluginStateinfo;

View File

@@ -1,4 +1,5 @@
import { Plugin, PanelPlugin, PanelDataFormat } from 'app/types';
import { PluginType } from '@grafana/ui';
export const getMockPlugins = (amount: number): Plugin[] => {
const plugins = [];
@@ -36,6 +37,7 @@ export const getMockPlugins = (amount: number): Plugin[] => {
export const getPanelPlugin = (options: Partial<PanelPlugin>): PanelPlugin => {
return {
id: options.id,
type: PluginType.panel,
name: options.id,
sort: options.sort || 1,
dataFormats: [PanelDataFormat.TimeSeries],
@@ -81,9 +83,9 @@ export const getMockPlugin = () => {
},
latestVersion: '1',
name: 'pretty cool plugin 1',
baseUrl: 'path/to/plugin',
pinned: false,
state: '',
type: '',
module: {},
};
type: PluginType.panel,
module: 'path/to/module',
} as Plugin;
};

View File

@@ -15,8 +15,9 @@ exports[`Render should render component 1`] = `
className="card-item-type"
>
<i
className="icon-gf icon-gf-"
className="icon-gf icon-gf-panel"
/>
panel
</div>
</div>
<div
@@ -63,8 +64,9 @@ exports[`Render should render has plugin section 1`] = `
className="card-item-type"
>
<i
className="icon-gf icon-gf-"
className="icon-gf icon-gf-panel"
/>
panel
</div>
<div
className="card-item-notice"

View File

@@ -1,10 +1,7 @@
import { AngularPanelPlugin, ReactPanelPlugin, PluginMetaInfo } from '@grafana/ui/src/types';
import { AngularPanelPlugin, ReactPanelPlugin, PluginMetaInfo, PluginMeta } from '@grafana/ui/src/types';
export interface PanelPlugin {
id: string;
name: string;
export interface PanelPlugin extends PluginMeta {
hideFromList?: boolean;
module: string;
baseUrl: string;
info: PluginMetaInfo;
sort: number;
@@ -19,18 +16,11 @@ export enum PanelDataFormat {
TimeSeries = 'time_series',
}
export interface Plugin {
export interface Plugin extends PluginMeta {
defaultNavUrl: string;
enabled: boolean;
hasUpdate: boolean;
id: string;
info: PluginMetaInfo;
latestVersion: string;
name: string;
pinned: boolean;
state: string;
type: string;
module: any;
}
export interface PluginDashboard {