QueryOptions.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Libraries
  2. import React, { PureComponent } from 'react';
  3. // Utils
  4. import { isValidTimeSpan } from 'app/core/utils/rangeutil';
  5. // Components
  6. import { Switch } from 'app/core/components/Switch/Switch';
  7. import { Input } from 'app/core/components/Form';
  8. import { EventsWithValidation } from 'app/core/components/Form/Input';
  9. import { InputStatus } from 'app/core/components/Form/Input';
  10. import DataSourceOption from './DataSourceOption';
  11. // Types
  12. import { PanelModel } from '../panel_model';
  13. import { ValidationEvents, DataSourceSelectItem } from 'app/types';
  14. const timeRangeValidationEvents: ValidationEvents = {
  15. [EventsWithValidation.onBlur]: [
  16. {
  17. rule: value => {
  18. if (!value) {
  19. return true;
  20. }
  21. return isValidTimeSpan(value);
  22. },
  23. errorMessage: 'Not a valid timespan',
  24. },
  25. ],
  26. };
  27. const emptyToNull = (value: string) => {
  28. return value === '' ? null : value;
  29. };
  30. interface Props {
  31. panel: PanelModel;
  32. datasource: DataSourceSelectItem;
  33. }
  34. export class QueryOptions extends PureComponent<Props> {
  35. onOverrideTime = (evt, status: InputStatus) => {
  36. const { value } = evt.target;
  37. const { panel } = this.props;
  38. const emptyToNullValue = emptyToNull(value);
  39. if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) {
  40. panel.timeFrom = emptyToNullValue;
  41. panel.refresh();
  42. }
  43. };
  44. onTimeShift = (evt, status: InputStatus) => {
  45. const { value } = evt.target;
  46. const { panel } = this.props;
  47. const emptyToNullValue = emptyToNull(value);
  48. if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) {
  49. panel.timeShift = emptyToNullValue;
  50. panel.refresh();
  51. }
  52. };
  53. onToggleTimeOverride = () => {
  54. const { panel } = this.props;
  55. panel.hideTimeOverride = !panel.hideTimeOverride;
  56. panel.refresh();
  57. };
  58. renderOptions() {
  59. const { datasource, panel } = this.props;
  60. const { queryOptions } = datasource.meta;
  61. if (!queryOptions) {
  62. return null;
  63. }
  64. const onChangeFn = (panelKey: string) => {
  65. return (value: string | number) => {
  66. panel[panelKey] = value;
  67. panel.refresh();
  68. };
  69. };
  70. const allOptions = {
  71. cacheTimeout: {
  72. label: 'Cache timeout',
  73. placeholder: '60',
  74. name: 'cacheTimeout',
  75. value: panel.cacheTimeout,
  76. tooltipInfo: (
  77. <>
  78. If your time series store has a query cache this option can override the default cache timeout. Specify a
  79. numeric value in seconds.
  80. </>
  81. ),
  82. },
  83. maxDataPoints: {
  84. label: 'Max data points',
  85. placeholder: 'auto',
  86. name: 'maxDataPoints',
  87. value: panel.maxDataPoints,
  88. tooltipInfo: (
  89. <>
  90. The maximum data points the query should return. For graphs this is automatically set to one data point per
  91. pixel.
  92. </>
  93. ),
  94. },
  95. minInterval: {
  96. label: 'Min time interval',
  97. placeholder: '0',
  98. name: 'minInterval',
  99. value: panel.interval,
  100. panelKey: 'interval',
  101. tooltipInfo: (
  102. <>
  103. A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '}
  104. <code>1m</code> if your data is written every minute. Access auto interval via variable{' '}
  105. <code>$__interval</code> for time range string and <code>$__interval_ms</code> for numeric variable that can
  106. be used in math expressions.
  107. </>
  108. ),
  109. },
  110. };
  111. return Object.keys(queryOptions).map(key => {
  112. const options = allOptions[key];
  113. return <DataSourceOption key={key} {...options} onChange={onChangeFn(allOptions[key].panelKey || key)} />;
  114. });
  115. }
  116. render = () => {
  117. const hideTimeOverride = this.props.panel.hideTimeOverride;
  118. return (
  119. <div className="gf-form-inline">
  120. {this.renderOptions()}
  121. <div className="gf-form">
  122. <span className="gf-form-label">Relative time</span>
  123. <Input
  124. type="text"
  125. className="width-6"
  126. placeholder="1h"
  127. onBlur={this.onOverrideTime}
  128. validationEvents={timeRangeValidationEvents}
  129. hideErrorMessage={true}
  130. />
  131. </div>
  132. <div className="gf-form">
  133. <span className="gf-form-label">Time shift</span>
  134. <Input
  135. type="text"
  136. className="width-6"
  137. placeholder="1h"
  138. onBlur={this.onTimeShift}
  139. validationEvents={timeRangeValidationEvents}
  140. hideErrorMessage={true}
  141. />
  142. </div>
  143. <div className="gf-form-inline">
  144. <Switch label="Hide time info" checked={hideTimeOverride} onChange={this.onToggleTimeOverride} />
  145. </div>
  146. </div>
  147. );
  148. };
  149. }