mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ReactMigration: Migrate DataSource HTTP Settings to React (#19452)
* Basic components for HTTP settings migration WIP * Add secureJsonFields to DataSourceSettings * Introduce datasource-http-settings-next directive for backward compatibility * fix lint * renames * rename fix * TagsInput component * move tags from app to grafana/ui * implement tagsinput on datasourcesettings * capitalize * new file for react directive for testing * some layout touch ups * FormField story * Minor touch ups * add url validation * using prevent default to prevent updating datasource when adding tag * using Stylefactory and fix tslint issue on MouseEvent * only show tlsauthsettings if tls or ca cert * fix url input length * fix for showAccessOptions * Implemented CertTextArea, removed commented code * removed commented / not used code * Rename and add more elements to Certification component * fixing newSecureJsonData * spelling * Fix issue with checkboxes being undefined * Removed old partials and minor fix * removed unused props from story
This commit is contained in:
committed by
Torkel Ödegaard
parent
cb0e80e7b9
commit
c9b11bfc7a
@@ -7,7 +7,13 @@ import { TagFilter } from './components/TagFilter/TagFilter';
|
||||
import { SideMenu } from './components/sidemenu/SideMenu';
|
||||
import { MetricSelect } from './components/Select/MetricSelect';
|
||||
import AppNotificationList from './components/AppNotifications/AppNotificationList';
|
||||
import { ColorPicker, SeriesColorPickerPopoverWithTheme, SecretFormField, DataLinksEditor } from '@grafana/ui';
|
||||
import {
|
||||
ColorPicker,
|
||||
SeriesColorPickerPopoverWithTheme,
|
||||
SecretFormField,
|
||||
DataLinksEditor,
|
||||
DataSourceHttpSettings,
|
||||
} from '@grafana/ui';
|
||||
import { FunctionEditor } from 'app/plugins/datasource/graphite/FunctionEditor';
|
||||
import { SearchField } from './components/search/SearchField';
|
||||
import { GraphContextMenu } from 'app/plugins/panel/graph/GraphContextMenu';
|
||||
@@ -111,4 +117,10 @@ export function registerAngularDirectives() {
|
||||
'onChange',
|
||||
['datasource', { watchDepth: 'reference' }],
|
||||
]);
|
||||
react2AngularDirective('datasourceHttpSettingsNext', DataSourceHttpSettings, [
|
||||
'defaultUrl',
|
||||
'showAccessOptions',
|
||||
'dataSourceConfig',
|
||||
['onChange', { watchDepth: 'reference', wrapApply: true }],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import tags from 'app/core/utils/tags';
|
||||
import { getTagColorsFromName } from '@grafana/ui';
|
||||
|
||||
export interface Props {
|
||||
label: string;
|
||||
@@ -15,7 +15,7 @@ export class TagBadge extends React.Component<Props, any> {
|
||||
|
||||
render() {
|
||||
const { label, removeIcon, count } = this.props;
|
||||
const { color, borderColor } = tags.getTagColorsFromName(label);
|
||||
const { color, borderColor } = getTagColorsFromName(label);
|
||||
const tagStyle = {
|
||||
backgroundColor: color,
|
||||
borderColor: borderColor,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import angular from 'angular';
|
||||
import { getTagColorsFromName } from '@grafana/ui';
|
||||
import $ from 'jquery';
|
||||
import coreModule from '../core_module';
|
||||
import tags from 'app/core/utils/tags';
|
||||
import 'vendor/tagsinput/bootstrap-tagsinput.js';
|
||||
|
||||
function setColor(name: string, element: JQuery) {
|
||||
const { color, borderColor } = tags.getTagColorsFromName(name);
|
||||
const { color, borderColor } = getTagColorsFromName(name);
|
||||
element.css('background-color', color);
|
||||
element.css('border-color', borderColor);
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
const TAG_COLORS = [
|
||||
'#E24D42',
|
||||
'#1F78C1',
|
||||
'#BA43A9',
|
||||
'#705DA0',
|
||||
'#466803',
|
||||
'#508642',
|
||||
'#447EBC',
|
||||
'#C15C17',
|
||||
'#890F02',
|
||||
'#757575',
|
||||
'#0A437C',
|
||||
'#6D1F62',
|
||||
'#584477',
|
||||
'#629E51',
|
||||
'#2F4F4F',
|
||||
'#BF1B00',
|
||||
'#806EB7',
|
||||
'#8a2eb8',
|
||||
'#699e00',
|
||||
'#000000',
|
||||
'#3F6833',
|
||||
'#2F575E',
|
||||
'#99440A',
|
||||
'#E0752D',
|
||||
'#0E4AB4',
|
||||
'#58140C',
|
||||
'#052B51',
|
||||
'#511749',
|
||||
'#3F2B5B',
|
||||
];
|
||||
|
||||
const TAG_BORDER_COLORS = [
|
||||
'#FF7368',
|
||||
'#459EE7',
|
||||
'#E069CF',
|
||||
'#9683C6',
|
||||
'#6C8E29',
|
||||
'#76AC68',
|
||||
'#6AA4E2',
|
||||
'#E7823D',
|
||||
'#AF3528',
|
||||
'#9B9B9B',
|
||||
'#3069A2',
|
||||
'#934588',
|
||||
'#7E6A9D',
|
||||
'#88C477',
|
||||
'#557575',
|
||||
'#E54126',
|
||||
'#A694DD',
|
||||
'#B054DE',
|
||||
'#8FC426',
|
||||
'#262626',
|
||||
'#658E59',
|
||||
'#557D84',
|
||||
'#BF6A30',
|
||||
'#FF9B53',
|
||||
'#3470DA',
|
||||
'#7E3A32',
|
||||
'#2B5177',
|
||||
'#773D6F',
|
||||
'#655181',
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns tag badge background and border colors based on hashed tag name.
|
||||
* @param name tag name
|
||||
*/
|
||||
export function getTagColorsFromName(name: string): { color: string; borderColor: string } {
|
||||
const hash = djb2(name.toLowerCase());
|
||||
const color = TAG_COLORS[Math.abs(hash % TAG_COLORS.length)];
|
||||
const borderColor = TAG_BORDER_COLORS[Math.abs(hash % TAG_BORDER_COLORS.length)];
|
||||
return { color, borderColor };
|
||||
}
|
||||
|
||||
function djb2(str: string) {
|
||||
let hash = 5381;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = (hash << 5) + hash + str.charCodeAt(i); /* hash * 33 + c */
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
export default {
|
||||
getTagColorsFromName,
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getTagColorsFromName } from '@grafana/ui';
|
||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||
import { NavModelSrv } from 'app/core/core';
|
||||
import tags from 'app/core/utils/tags';
|
||||
|
||||
export default class AdminListUsersCtrl {
|
||||
users: any;
|
||||
@@ -63,7 +63,7 @@ function getAuthLabelStyle(label: string) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const { color, borderColor } = tags.getTagColorsFromName(label);
|
||||
const { color, borderColor } = getTagColorsFromName(label);
|
||||
return {
|
||||
'background-color': color,
|
||||
'border-color': borderColor,
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
<div class="gf-form-group">
|
||||
<h3 class="page-heading">HTTP</h3>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form max-width-30">
|
||||
<span class="gf-form-label width-10">URL</span>
|
||||
<input class="gf-form-input gf-form-input--has-help-icon" type="text"
|
||||
ng-model='current.url' placeholder="{{suggestUrl}}"
|
||||
bs-typeahead="getSuggestUrls" min-length="0"
|
||||
ng-pattern="/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/" required></input>
|
||||
<info-popover mode="right-absolute">
|
||||
<p>Specify a complete HTTP URL (for example http://your_server:8080)</p>
|
||||
<span ng-show="current.access === 'direct'">
|
||||
Your access method is <em>Browser</em>, this means the URL
|
||||
needs to be accessible from the browser.
|
||||
</span>
|
||||
<span ng-show="current.access === 'proxy'">
|
||||
Your access method is <em>Server</em>, this means the URL
|
||||
needs to be accessible from the grafana backend/server.
|
||||
</span>
|
||||
</info-popover>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-inline" ng-if="showAccessOption">
|
||||
<div class="gf-form max-width-30">
|
||||
<span class="gf-form-label width-10">Access</span>
|
||||
<div class="gf-form-select-wrapper max-width-24">
|
||||
<select class="gf-form-input" ng-model="current.access" ng-options="f.key as f.value for f in [{key: 'proxy', value: 'Server (Default)'}, { key: 'direct', value: 'Browser'}]"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword pointer" ng-click="toggleAccessHelp()">
|
||||
Help
|
||||
<i class="fa fa-caret-down" ng-show="showAccessHelp"></i>
|
||||
<i class="fa fa-caret-right" ng-hide="showAccessHelp"> </i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grafana-info-box m-t-2" ng-show="showAccessHelp">
|
||||
<p>
|
||||
Access mode controls how requests to the data source will be handled.
|
||||
<strong><i>Server</i></strong> should be the preferred way if nothing else stated.
|
||||
</p>
|
||||
<div class="alert-title">Server access mode (Default):</div>
|
||||
<p>
|
||||
All requests will be made from the browser to Grafana backend/server which in turn will forward the requests to the data source
|
||||
and by that circumvent possible Cross-Origin Resource Sharing (CORS) requirements.
|
||||
The URL needs to be accessible from the grafana backend/server if you select this access mode.
|
||||
</p>
|
||||
<div class="alert-title">Browser access mode:</div>
|
||||
<p>
|
||||
All requests will be made from the browser directly to the data source and may be subject to
|
||||
Cross-Origin Resource Sharing (CORS) requirements. The URL needs to be accessible from the browser if you select this
|
||||
access mode.
|
||||
</div>
|
||||
|
||||
<div class="gf-form-inline" ng-if="current.access=='proxy'">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-10">Whitelisted Cookies</span>
|
||||
<bootstrap-tagsinput ng-model="current.jsonData.keepCookies" width-class="width-20 gf-form-input--has-help-icon" tagclass="label label-tag" placeholder="Add Name">
|
||||
</bootstrap-tagsinput>
|
||||
<info-popover mode="right-absolute">
|
||||
Grafana Proxy deletes forwarded cookies by default. Specify cookies by name that should be forwarded to the data source.
|
||||
</info-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="page-heading">Auth</h3>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-checkbox class="gf-form" label="Basic Auth" checked="current.basicAuth" label-class="width-13" switch-class="max-width-6"></gf-form-checkbox>
|
||||
<gf-form-checkbox class="gf-form" label="With Credentials" tooltip="Whether credentials such as cookies or auth
|
||||
headers should be sent with cross-site requests." checked="current.withCredentials" label-class="width-13"
|
||||
switch-class="max-width-6"></gf-form-checkbox>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-checkbox class="gf-form" ng-if="current.access=='proxy'" label="TLS Client Auth" label-class="width-13"
|
||||
checked="current.jsonData.tlsAuth" switch-class="max-width-6"></gf-form-checkbox>
|
||||
<gf-form-checkbox class="gf-form" ng-if="current.access=='proxy'" label="With CA Cert" tooltip="Needed for
|
||||
verifing self-signed TLS Certs" checked="current.jsonData.tlsAuthWithCACert" label-class="width-13"
|
||||
switch-class="max-width-6"></gf-form-checkbox>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-checkbox class="gf-form" ng-if="current.access=='proxy'" label="Skip TLS Verify" label-class="width-13"
|
||||
checked="current.jsonData.tlsSkipVerify" switch-class="max-width-6"></gf-form-checkbox>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<gf-form-checkbox class="gf-form" ng-if="current.access=='proxy'" label="Forward OAuth Identity" label-class="width-13" tooltip="Forward the user's upstream OAuth identity to the datasource (Their access token gets passed along)." checked="current.jsonData.oauthPassThru" switch-class="max-width-6"></gf-form-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group" ng-if="current.basicAuth">
|
||||
<h6>Basic Auth Details</h6>
|
||||
<div class="gf-form" ng-if="current.basicAuth">
|
||||
<span class="gf-form-label width-10">User</span>
|
||||
<input class="gf-form-input max-width-21" type="text" ng-model='current.basicAuthUser' placeholder="user" required></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<secret-form-field
|
||||
isConfigured="current.basicAuthPassword || current.secureJsonFields.basicAuthPassword"
|
||||
value="current.secureJsonData.basicAuthPassword || ''"
|
||||
on-reset="onBasicAuthPasswordReset"
|
||||
on-change="onBasicAuthPasswordChange"
|
||||
inputWidth="18"
|
||||
labelWidth="10"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<datasource-tls-auth-settings current="current" ng-if="(current.jsonData.tlsAuth || current.jsonData.tlsAuthWithCACert) && current.access=='proxy'">
|
||||
</datasource-tls-auth-settings>
|
||||
@@ -0,0 +1 @@
|
||||
<datasource-http-settings-next on-change="onChange" dataSourceConfig="current" showAccessOptions="showAccessOption" defaultUrl="suggestUrl" />
|
||||
@@ -1,62 +0,0 @@
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form">
|
||||
<h6>TLS Auth Details</h6>
|
||||
<info-popover mode="header">TLS Certs are encrypted and stored in the Grafana database.</info-popover>
|
||||
</div>
|
||||
<div ng-if="current.jsonData.tlsAuthWithCACert">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form gf-form--v-stretch"><label class="gf-form-label width-7">CA Cert</label></div>
|
||||
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsCACert">
|
||||
<textarea
|
||||
rows="7"
|
||||
class="gf-form-input gf-form-textarea"
|
||||
ng-model="current.secureJsonData.tlsCACert"
|
||||
placeholder="Begins with -----BEGIN CERTIFICATE-----"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div class="gf-form" ng-if="current.secureJsonFields.tlsCACert">
|
||||
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured" />
|
||||
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsCACert = false">reset</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="current.jsonData.tlsAuth">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form gf-form--v-stretch"><label class="gf-form-label width-7">Client Cert</label></div>
|
||||
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsClientCert">
|
||||
<textarea
|
||||
rows="7"
|
||||
class="gf-form-input gf-form-textarea"
|
||||
ng-model="current.secureJsonData.tlsClientCert"
|
||||
placeholder="Begins with -----BEGIN CERTIFICATE-----"
|
||||
required
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="gf-form" ng-if="current.secureJsonFields.tlsClientCert">
|
||||
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured" />
|
||||
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsClientCert = false"
|
||||
>reset</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form gf-form--v-stretch"><label class="gf-form-label width-7">Client Key</label></div>
|
||||
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsClientKey">
|
||||
<textarea
|
||||
rows="7"
|
||||
class="gf-form-input gf-form-textarea"
|
||||
ng-model="current.secureJsonData.tlsClientKey"
|
||||
placeholder="Begins with -----BEGIN RSA PRIVATE KEY-----"
|
||||
required
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="gf-form" ng-if="current.secureJsonFields.tlsClientKey">
|
||||
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured" />
|
||||
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsClientKey = false">reset</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,5 +1,4 @@
|
||||
import { coreModule } from 'app/core/core';
|
||||
import { createChangeHandler, createResetHandler, PasswordFieldEnum } from '../utils/passwordHandlers';
|
||||
|
||||
coreModule.directive('datasourceHttpSettings', () => {
|
||||
return {
|
||||
@@ -8,22 +7,14 @@ coreModule.directive('datasourceHttpSettings', () => {
|
||||
suggestUrl: '@',
|
||||
noDirectAccess: '@',
|
||||
},
|
||||
templateUrl: 'public/app/features/datasources/partials/http_settings.html',
|
||||
templateUrl: 'public/app/features/datasources/partials/http_settings_next.html',
|
||||
link: {
|
||||
pre: ($scope: any, elem, attrs) => {
|
||||
pre: ($scope: any) => {
|
||||
// do not show access option if direct access is disabled
|
||||
$scope.showAccessOption = $scope.noDirectAccess !== 'true';
|
||||
$scope.showAccessHelp = false;
|
||||
$scope.toggleAccessHelp = () => {
|
||||
$scope.showAccessHelp = !$scope.showAccessHelp;
|
||||
$scope.onChange = (datasourceSetting: any) => {
|
||||
$scope.current = datasourceSetting;
|
||||
};
|
||||
|
||||
$scope.getSuggestUrls = () => {
|
||||
return [$scope.suggestUrl];
|
||||
};
|
||||
|
||||
$scope.onBasicAuthPasswordReset = createResetHandler($scope, PasswordFieldEnum.BasicAuthPassword);
|
||||
$scope.onBasicAuthPasswordChange = createChangeHandler($scope, PasswordFieldEnum.BasicAuthPassword);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user