mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
renders angular component
This commit is contained in:
34
public/app/features/datasources/settings/BasicSettings.tsx
Normal file
34
public/app/features/datasources/settings/BasicSettings.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import React, { SFC } from 'react';
|
||||||
|
import { Label } from '../../../core/components/Forms/Forms';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
dataSourceName: string;
|
||||||
|
onChange: (name: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BasicSettings: SFC<Props> = ({ dataSourceName, onChange }) => {
|
||||||
|
return (
|
||||||
|
<div className="gf-form-group">
|
||||||
|
<div className="gf-form max-width-30">
|
||||||
|
<Label
|
||||||
|
tooltip={
|
||||||
|
'The name is used when you select the data source in panels. The Default data source is' +
|
||||||
|
'preselected in new panels.'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Name
|
||||||
|
</Label>
|
||||||
|
<input
|
||||||
|
className="gf-form-input max-width-23"
|
||||||
|
type="text"
|
||||||
|
value={dataSourceName}
|
||||||
|
placeholder="Name"
|
||||||
|
onChange={event => onChange(event.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BasicSettings;
|
||||||
25
public/app/features/datasources/settings/ButtonRow.tsx
Normal file
25
public/app/features/datasources/settings/ButtonRow.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import React, { SFC } from 'react';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
isReadOnly: boolean;
|
||||||
|
onDelete: (event) => void;
|
||||||
|
onSubmit: (event) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ButtonRow: SFC<Props> = ({ isReadOnly, onDelete, onSubmit }) => {
|
||||||
|
return (
|
||||||
|
<div className="gf-form-button-row">
|
||||||
|
<button type="submit" className="btn btn-success" disabled={isReadOnly} onClick={event => onSubmit(event)}>
|
||||||
|
Save & Test
|
||||||
|
</button>
|
||||||
|
<button type="submit" className="btn btn-danger" disabled={isReadOnly} onClick={event => onDelete(event)}>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
<a className="btn btn-inverse" href="/datasources">
|
||||||
|
Back
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ButtonRow;
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { DataSource, NavModel, Plugin } from 'app/types';
|
import { DataSource, NavModel, Plugin } from 'app/types/';
|
||||||
import PageHeader from '../../core/components/PageHeader/PageHeader';
|
import PageHeader from '../../../core/components/PageHeader/PageHeader';
|
||||||
import DataSourcePluginSettings from './DataSourcePluginSettings';
|
import PageLoader from '../../../core/components/PageLoader/PageLoader';
|
||||||
import { loadDataSource, setDataSourceName } from './state/actions';
|
import PluginSettings from './PluginSettings';
|
||||||
import { getNavModel } from '../../core/selectors/navModel';
|
import BasicSettings from './BasicSettings';
|
||||||
import { getRouteParamsId } from '../../core/selectors/location';
|
import ButtonRow from './ButtonRow';
|
||||||
import { Label } from '../../core/components/Forms/Forms';
|
import { loadDataSource, setDataSourceName } from '../state/actions';
|
||||||
import PageLoader from '../../core/components/PageLoader/PageLoader';
|
import { getNavModel } from '../../../core/selectors/navModel';
|
||||||
import { getDataSource } from './state/selectors';
|
import { getRouteParamsId } from '../../../core/selectors/location';
|
||||||
|
import { getDataSource, getDataSourceMeta } from '../state/selectors';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
navModel: NavModel;
|
navModel: NavModel;
|
||||||
@@ -45,7 +46,7 @@ export class DataSourceSettings extends PureComponent<Props, State> {
|
|||||||
console.log(event);
|
console.log(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
isReadyOnly() {
|
isReadOnly() {
|
||||||
return this.props.dataSource.readOnly === true;
|
return this.props.dataSource.readOnly === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,59 +88,27 @@ export class DataSourceSettings extends PureComponent<Props, State> {
|
|||||||
<div className="page-container page-body">
|
<div className="page-container page-body">
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={this.onSubmit}>
|
<form onSubmit={this.onSubmit}>
|
||||||
<div className="gf-form-group">
|
<BasicSettings
|
||||||
<div className="gf-form max-width-30">
|
dataSourceName={this.props.dataSource.name}
|
||||||
<Label
|
onChange={name => this.props.setDataSourceName(name)}
|
||||||
tooltip={
|
/>
|
||||||
'The name is used when you select the data source in panels. The Default data source is' +
|
|
||||||
'preselected in new panels.'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Name
|
|
||||||
</Label>
|
|
||||||
<input
|
|
||||||
className="gf-form-input max-width-23"
|
|
||||||
type="text"
|
|
||||||
value={this.props.dataSource.name}
|
|
||||||
placeholder="Name"
|
|
||||||
onChange={event => this.props.setDataSourceName(event.target.value)}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{this.shouldRenderInfoBox() && <div className="grafana-info-box">{this.getInfoText()}</div>}
|
{this.shouldRenderInfoBox() && <div className="grafana-info-box">{this.getInfoText()}</div>}
|
||||||
|
|
||||||
{this.isReadyOnly() ? (
|
{this.isReadOnly() ? (
|
||||||
<div className="grafana-info-box span8">
|
<div className="grafana-info-box span8">
|
||||||
This datasource was added by config and cannot be modified using the UI. Please contact your server
|
This datasource was added by config and cannot be modified using the UI. Please contact your server
|
||||||
admin to update this datasource.
|
admin to update this datasource.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<DataSourcePluginSettings dataSource={dataSource} dataSourceMeta={dataSourceMeta} />
|
dataSourceMeta.module && <PluginSettings dataSource={dataSource} dataSourceMeta={dataSourceMeta} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="gf-form-button-row">
|
<ButtonRow
|
||||||
<button
|
onSubmit={event => this.onSubmit(event)}
|
||||||
type="submit"
|
isReadOnly={this.isReadOnly()}
|
||||||
className="btn btn-success"
|
onDelete={event => this.onDelete(event)}
|
||||||
disabled={this.isReadyOnly()}
|
/>
|
||||||
onClick={this.onSubmit}
|
|
||||||
>
|
|
||||||
Save & Test
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="btn btn-danger"
|
|
||||||
disabled={this.isReadyOnly()}
|
|
||||||
onClick={this.onDelete}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</button>
|
|
||||||
<a className="btn btn-inverse" href="/datasources">
|
|
||||||
Back
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -151,11 +120,12 @@ export class DataSourceSettings extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
const pageId = getRouteParamsId(state.location);
|
const pageId = getRouteParamsId(state.location);
|
||||||
|
const dataSource = getDataSource(state.dataSources, pageId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
navModel: getNavModel(state.navIndex, `datasource-settings-${pageId}`),
|
navModel: getNavModel(state.navIndex, `datasource-settings-${pageId}`),
|
||||||
dataSource: getDataSource(state.dataSources, pageId),
|
dataSource: getDataSource(state.dataSources, pageId),
|
||||||
dataSourceMeta: state.dataSources.dataSourceMeta,
|
dataSourceMeta: getDataSourceMeta(state.dataSources, dataSource.type),
|
||||||
pageId: pageId,
|
pageId: pageId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,29 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { DataSource, Plugin } from 'app/types';
|
import { DataSource, Plugin } from 'app/types/';
|
||||||
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
|
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
|
||||||
import { importPluginModule } from '../plugins/plugin_loader';
|
|
||||||
interface Props {
|
interface Props {
|
||||||
dataSource: DataSource;
|
dataSource: DataSource;
|
||||||
dataSourceMeta: Plugin;
|
dataSourceMeta: Plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DataSourcePluginSettings extends PureComponent<Props> {
|
export class PluginSettings extends PureComponent<Props> {
|
||||||
element: any;
|
element: any;
|
||||||
component: AngularComponent;
|
component: AngularComponent;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const { dataSource, dataSourceMeta } = this.props;
|
||||||
|
|
||||||
if (!this.element) {
|
if (!this.element) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
importPluginModule(this.props.dataSourceMeta.module).then(pluginExports => {
|
|
||||||
console.log(pluginExports);
|
|
||||||
});
|
|
||||||
|
|
||||||
const loader = getAngularLoader();
|
const loader = getAngularLoader();
|
||||||
const template = '<plugin-component type="datasource-config-ctrl" />';
|
const template = '<plugin-component type="datasource-config-ctrl" />';
|
||||||
const scopeProps = {
|
const scopeProps = {
|
||||||
ctrl: {
|
ctrl: {
|
||||||
dataSourceMeta: this.props.dataSourceMeta,
|
datasourceMeta: dataSourceMeta,
|
||||||
current: this.props.dataSource,
|
current: dataSource,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -37,4 +35,4 @@ export class DataSourcePluginSettings extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DataSourcePluginSettings;
|
export default PluginSettings;
|
||||||
@@ -23,6 +23,14 @@ export const getDataSource = (state, dataSourceId): DataSource | null => {
|
|||||||
return {} as DataSource;
|
return {} as DataSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDataSourceMeta = (state, type): Plugin => {
|
||||||
|
if (state.dataSourceMeta.id === type) {
|
||||||
|
return state.dataSourceMeta;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {} as Plugin;
|
||||||
|
};
|
||||||
|
|
||||||
export const getDataSourcesSearchQuery = state => state.searchQuery;
|
export const getDataSourcesSearchQuery = state => state.searchQuery;
|
||||||
export const getDataSourcesLayoutMode = state => state.layoutMode;
|
export const getDataSourcesLayoutMode = state => state.layoutMode;
|
||||||
export const getDataSourcesCount = state => state.dataSourcesCount;
|
export const getDataSourcesCount = state => state.dataSourcesCount;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import DataSourcesListPage from 'app/features/datasources/DataSourcesListPage';
|
|||||||
import NewDataSourcePage from '../features/datasources/NewDataSourcePage';
|
import NewDataSourcePage from '../features/datasources/NewDataSourcePage';
|
||||||
import UsersListPage from 'app/features/users/UsersListPage';
|
import UsersListPage from 'app/features/users/UsersListPage';
|
||||||
import DataSourceDashboards from 'app/features/datasources/DataSourceDashboards';
|
import DataSourceDashboards from 'app/features/datasources/DataSourceDashboards';
|
||||||
import DataSourceSettings from '../features/datasources/DataSourceSettings';
|
import DataSourceSettings from '../features/datasources/settings/DataSourceSettings';
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
export function setupAngularRoutes($routeProvider, $locationProvider) {
|
export function setupAngularRoutes($routeProvider, $locationProvider) {
|
||||||
|
|||||||
@@ -4,22 +4,19 @@ const merge = require('webpack-merge');
|
|||||||
const common = require('./webpack.common.js');
|
const common = require('./webpack.common.js');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
|
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
|
||||||
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||||
|
|
||||||
module.exports = merge(common, {
|
module.exports = merge(common, {
|
||||||
entry: {
|
entry: {
|
||||||
app: [
|
app: ['webpack-dev-server/client?http://localhost:3333', './public/app/dev.ts'],
|
||||||
'webpack-dev-server/client?http://localhost:3333',
|
|
||||||
'./public/app/dev.ts',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, '../../public/build'),
|
path: path.resolve(__dirname, '../../public/build'),
|
||||||
filename: '[name].[hash].js',
|
filename: '[name].[hash].js',
|
||||||
publicPath: "/public/build/",
|
publicPath: '/public/build/',
|
||||||
pathinfo: false,
|
pathinfo: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -34,8 +31,8 @@ module.exports = merge(common, {
|
|||||||
hot: true,
|
hot: true,
|
||||||
port: 3333,
|
port: 3333,
|
||||||
proxy: {
|
proxy: {
|
||||||
'!/public/build': 'http://localhost:3000'
|
'!/public/build': 'http://localhost:3000',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
optimization: {
|
optimization: {
|
||||||
@@ -47,40 +44,39 @@ module.exports = merge(common, {
|
|||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /(?!.*\.test)\.tsx$/,
|
test: /(?!.*\.test)\.(ts|tsx)$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: [{
|
use: [
|
||||||
loader: 'babel-loader',
|
{
|
||||||
options: {
|
loader: 'babel-loader',
|
||||||
cacheDirectory: true,
|
options: {
|
||||||
babelrc: false,
|
cacheDirectory: true,
|
||||||
plugins: [
|
babelrc: false,
|
||||||
'syntax-dynamic-import',
|
plugins: ['syntax-dynamic-import', 'react-hot-loader/babel'],
|
||||||
'react-hot-loader/babel'
|
},
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: 'ts-loader',
|
|
||||||
options: {
|
|
||||||
transpileOnly: true,
|
|
||||||
experimentalWatchApi: true
|
|
||||||
},
|
},
|
||||||
}],
|
{
|
||||||
|
loader: 'ts-loader',
|
||||||
|
options: {
|
||||||
|
transpileOnly: true,
|
||||||
|
experimentalWatchApi: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.scss$/,
|
test: /\.scss$/,
|
||||||
use: [
|
use: [
|
||||||
"style-loader", // creates style nodes from JS strings
|
'style-loader', // creates style nodes from JS strings
|
||||||
"css-loader", // translates CSS into CommonJS
|
'css-loader', // translates CSS into CommonJS
|
||||||
"sass-loader" // compiles Sass to CSS
|
'sass-loader', // compiles Sass to CSS
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(png|jpg|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
|
test: /\.(png|jpg|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
|
||||||
loader: 'file-loader'
|
loader: 'file-loader',
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
@@ -89,16 +85,16 @@ module.exports = merge(common, {
|
|||||||
filename: path.resolve(__dirname, '../../public/views/index.html'),
|
filename: path.resolve(__dirname, '../../public/views/index.html'),
|
||||||
template: path.resolve(__dirname, '../../public/views/index.template.html'),
|
template: path.resolve(__dirname, '../../public/views/index.template.html'),
|
||||||
inject: 'body',
|
inject: 'body',
|
||||||
alwaysWriteToDisk: true
|
alwaysWriteToDisk: true,
|
||||||
}),
|
}),
|
||||||
new HtmlWebpackHarddiskPlugin(),
|
new HtmlWebpackHarddiskPlugin(),
|
||||||
new webpack.NamedModulesPlugin(),
|
new webpack.NamedModulesPlugin(),
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'GRAFANA_THEME': JSON.stringify(process.env.GRAFANA_THEME || 'dark'),
|
GRAFANA_THEME: JSON.stringify(process.env.GRAFANA_THEME || 'dark'),
|
||||||
'process.env': {
|
'process.env': {
|
||||||
'NODE_ENV': JSON.stringify('development')
|
NODE_ENV: JSON.stringify('development'),
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user