diff --git a/public/app/core/components/Form/Input.tsx b/public/app/core/components/Form/Input.tsx index 6ba58b45e91..f69aac9759f 100644 --- a/public/app/core/components/Form/Input.tsx +++ b/public/app/core/components/Form/Input.tsx @@ -1,4 +1,4 @@ -import React, { PureComponent } from 'react'; +import React, { PureComponent } from 'react'; import { ValidationEvents, ValidationRule } from 'app/types'; import { validate, hasValidationEvent } from 'app/core/utils/validate'; @@ -76,7 +76,7 @@ export class Input extends PureComponent { render() { const { validationEvents, className, hideErrorMessage, ...restProps } = this.props; const { error } = this.state; - const inputClassName = 'gf-form-input' + (this.isInvalid ? ' invalid' : ''); + const inputClassName = 'gf-form-input' + (this.isInvalid ? ' invalid' : '') + ' ' + className; const inputElementProps = this.populateEventPropsWithStatus(restProps, validationEvents); return ( diff --git a/public/app/features/dashboard/dashgrid/QueriesTab.tsx b/public/app/features/dashboard/dashgrid/QueriesTab.tsx index 53e066ef43d..e2c64da9b29 100644 --- a/public/app/features/dashboard/dashgrid/QueriesTab.tsx +++ b/public/app/features/dashboard/dashgrid/QueriesTab.tsx @@ -4,12 +4,11 @@ import Remarkable from 'remarkable'; import _ from 'lodash'; // Components -import DataSourceOption from './DataSourceOption'; +import './../../panel/metrics_tab'; import { EditorTabBody } from './EditorTabBody'; import { DataSourcePicker } from './DataSourcePicker'; import { QueryInspector } from './QueryInspector'; -import { TimeRangeOptions } from './TimeRangeOptions'; -import './../../panel/metrics_tab'; +import { QueryOptions } from './QueryOptions'; import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab'; // Services @@ -157,75 +156,6 @@ export class QueriesTab extends PureComponent { } }; - renderOptions = close => { - const { currentDS } = this.state; - const { queryOptions } = currentDS.meta; - const { panel } = this.props; - - const onChangeFn = (panelKey: string) => { - return (value: string | number) => { - panel[panelKey] = value; - panel.refresh(); - }; - }; - - const allOptions = { - cacheTimeout: { - label: 'Cache timeout', - placeholder: '60', - name: 'cacheTimeout', - value: panel.cacheTimeout, - tooltipInfo: ( - <> - If your time series store has a query cache this option can override the default cache timeout. Specify a - numeric value in seconds. - - ), - }, - maxDataPoints: { - label: 'Max data points', - placeholder: 'auto', - name: 'maxDataPoints', - value: panel.maxDataPoints, - tooltipInfo: ( - <> - The maximum data points the query should return. For graphs this is automatically set to one data point per - pixel. - - ), - }, - minInterval: { - label: 'Min time interval', - placeholder: '0', - name: 'minInterval', - value: panel.interval, - panelKey: 'interval', - tooltipInfo: ( - <> - A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '} - 1m if your data is written every minute. Access auto interval via variable{' '} - $__interval for time range string and $__interval_ms for numeric variable that can - be used in math expressions. - - ), - }, - }; - - const dsOptions = queryOptions - ? Object.keys(queryOptions).map(key => { - const options = allOptions[key]; - return ; - }) - : null; - - return ( - <> - - {dsOptions} - - ); - }; - renderQueryInspector = () => { const { panel } = this.props; return ; @@ -323,40 +253,41 @@ export class QueriesTab extends PureComponent { render: this.renderHelp, }; - const options = { - title: 'Time Range', - icon: '', - disabled: false, - render: this.renderOptions, - }; - return ( - -
-
Queries
-
-
-
(this.element = element)} /> - -
-
- - {!isAddingMixed && ( - - )} - {isAddingMixed && this.renderMixedPicker()} + + <> +
+
Queries
+
+
+
(this.element = element)} /> + +
+
+ + {!isAddingMixed && ( + + )} + {isAddingMixed && this.renderMixedPicker()} +
-
+
+
Options
+
+ +
+
+
); } diff --git a/public/app/features/dashboard/dashgrid/QueryOptions.tsx b/public/app/features/dashboard/dashgrid/QueryOptions.tsx new file mode 100644 index 00000000000..c6d5fecb6d4 --- /dev/null +++ b/public/app/features/dashboard/dashgrid/QueryOptions.tsx @@ -0,0 +1,167 @@ +// Libraries +import React, { PureComponent } from 'react'; + +// Utils +import { isValidTimeSpan } from 'app/core/utils/rangeutil'; + +// Components +import { Switch } from 'app/core/components/Switch/Switch'; +import { Input } from 'app/core/components/Form'; +import { EventsWithValidation } from 'app/core/components/Form/Input'; +import { InputStatus } from 'app/core/components/Form/Input'; +import DataSourceOption from './DataSourceOption'; + +// Types +import { PanelModel } from '../panel_model'; +import { ValidationEvents, DataSourceSelectItem } from 'app/types'; + +const timeRangeValidationEvents: ValidationEvents = { + [EventsWithValidation.onBlur]: [ + { + rule: value => { + if (!value) { + return true; + } + return isValidTimeSpan(value); + }, + errorMessage: 'Not a valid timespan', + }, + ], +}; + +const emptyToNull = (value: string) => { + return value === '' ? null : value; +}; + +interface Props { + panel: PanelModel; + datasource: DataSourceSelectItem; +} + +export class QueryOptions extends PureComponent { + onOverrideTime = (evt, status: InputStatus) => { + const { value } = evt.target; + const { panel } = this.props; + const emptyToNullValue = emptyToNull(value); + if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) { + panel.timeFrom = emptyToNullValue; + panel.refresh(); + } + }; + + onTimeShift = (evt, status: InputStatus) => { + const { value } = evt.target; + const { panel } = this.props; + const emptyToNullValue = emptyToNull(value); + if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) { + panel.timeShift = emptyToNullValue; + panel.refresh(); + } + }; + + onToggleTimeOverride = () => { + const { panel } = this.props; + panel.hideTimeOverride = !panel.hideTimeOverride; + panel.refresh(); + }; + + renderOptions() { + const { datasource, panel } = this.props; + const { queryOptions } = datasource.meta; + + if (!queryOptions) { + return null; + } + + const onChangeFn = (panelKey: string) => { + return (value: string | number) => { + panel[panelKey] = value; + panel.refresh(); + }; + }; + + const allOptions = { + cacheTimeout: { + label: 'Cache timeout', + placeholder: '60', + name: 'cacheTimeout', + value: panel.cacheTimeout, + tooltipInfo: ( + <> + If your time series store has a query cache this option can override the default cache timeout. Specify a + numeric value in seconds. + + ), + }, + maxDataPoints: { + label: 'Max data points', + placeholder: 'auto', + name: 'maxDataPoints', + value: panel.maxDataPoints, + tooltipInfo: ( + <> + The maximum data points the query should return. For graphs this is automatically set to one data point per + pixel. + + ), + }, + minInterval: { + label: 'Min time interval', + placeholder: '0', + name: 'minInterval', + value: panel.interval, + panelKey: 'interval', + tooltipInfo: ( + <> + A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '} + 1m if your data is written every minute. Access auto interval via variable{' '} + $__interval for time range string and $__interval_ms for numeric variable that can + be used in math expressions. + + ), + }, + }; + + return Object.keys(queryOptions).map(key => { + const options = allOptions[key]; + return ; + }); + } + + render = () => { + const hideTimeOverride = this.props.panel.hideTimeOverride; + return ( +
+ {this.renderOptions()} + +
+ Relative time + +
+ +
+ Time shift + +
+ +
+ +
+
+ ); + }; +} diff --git a/public/app/features/dashboard/dashgrid/TimeRangeOptions.tsx b/public/app/features/dashboard/dashgrid/TimeRangeOptions.tsx deleted file mode 100644 index 00371fa960b..00000000000 --- a/public/app/features/dashboard/dashgrid/TimeRangeOptions.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import React, { PureComponent } from 'react'; -import { Switch } from 'app/core/components/Switch/Switch'; -import { Input } from 'app/core/components/Form'; -import { isValidTimeSpan } from 'app/core/utils/rangeutil'; -import { ValidationEvents } from 'app/types'; -import { EventsWithValidation } from 'app/core/components/Form/Input'; -import { PanelModel } from '../panel_model'; -import { InputStatus } from 'app/core/components/Form/Input'; - -const timeRangeValidationEvents: ValidationEvents = { - [EventsWithValidation.onBlur]: [ - { - rule: value => { - if (!value) { - return true; - } - return isValidTimeSpan(value); - }, - errorMessage: 'Not a valid timespan', - }, - ], -}; - -const emptyToNull = (value: string) => { - return value === '' ? null : value; -}; - -interface Props { - panel: PanelModel; -} - -export class TimeRangeOptions extends PureComponent { - onOverrideTime = (evt, status: InputStatus) => { - const { value } = evt.target; - const { panel } = this.props; - const emptyToNullValue = emptyToNull(value); - if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) { - panel.timeFrom = emptyToNullValue; - panel.refresh(); - } - }; - - onTimeShift = (evt, status: InputStatus) => { - const { value } = evt.target; - const { panel } = this.props; - const emptyToNullValue = emptyToNull(value); - if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) { - panel.timeShift = emptyToNullValue; - panel.refresh(); - } - }; - - onToggleTimeOverride = () => { - const { panel } = this.props; - panel.hideTimeOverride = !panel.hideTimeOverride; - panel.refresh(); - }; - - render = () => { - const hideTimeOverride = this.props.panel.hideTimeOverride; - return ( - <> -
Time Range
- -
-
- Override relative time - -
- -
- Add time shift - -
- -
- -
-
- - ); - }; -} diff --git a/public/app/features/dashboard/panellinks/module.html b/public/app/features/dashboard/panellinks/module.html index 96d9b785a1b..0dcb0ef3ed6 100644 --- a/public/app/features/dashboard/panellinks/module.html +++ b/public/app/features/dashboard/panellinks/module.html @@ -1,8 +1,4 @@
-
- Drilldown / detail linkThese links appear in the dropdown menu in the panel menu.
- -
diff --git a/public/app/features/panel/partials/general_tab.html b/public/app/features/panel/partials/general_tab.html index 03aab78c407..13ca0380dbc 100644 --- a/public/app/features/panel/partials/general_tab.html +++ b/public/app/features/panel/partials/general_tab.html @@ -1,37 +1,49 @@ -
-
-
Info
-
- Title - -
-
- Description - -
- -
- -
-
Repeat
-
- For each value of - -
-
- Direction - -
-
- Min width - -
-
- - +
+
Information
+
+
+
+ Title + +
+ +
+
+
+ Description + +
+
+
+
+
+
Repeating
+
+
+
+ Repat + +
+
+ Direction + +
+
+ Min width + +
+
+
+
+
+
Drildown Links
+
+ +
+
diff --git a/public/sass/components/_panel_editor.scss b/public/sass/components/_panel_editor.scss index daa4382a690..7195d0c181a 100644 --- a/public/sass/components/_panel_editor.scss +++ b/public/sass/components/_panel_editor.scss @@ -262,4 +262,8 @@ .panel-option-section__body { padding: 20px; background: $page-bg; + + &--queries { + min-height: 300px; + } }