DashboardQueryEditor.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Libraries
  2. import React, { PureComponent } from 'react';
  3. // Types
  4. import { Select, DataQuery, DataQueryError, PanelData } from '@grafana/ui';
  5. import { DataFrame, SelectableValue } from '@grafana/data';
  6. import { DashboardQuery } from './types';
  7. import config from 'app/core/config';
  8. import { css } from 'emotion';
  9. import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
  10. import { PanelModel } from 'app/features/dashboard/state';
  11. import { SHARED_DASHBODARD_QUERY } from './SharedQueryRunner';
  12. import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
  13. import { filterPanelDataToQuery } from 'app/features/dashboard/panel_editor/QueryEditorRow';
  14. type ResultInfo = {
  15. img: string; // The Datasource
  16. refId: string;
  17. query: string; // As text
  18. data: DataFrame[];
  19. error?: DataQueryError;
  20. };
  21. function getQueryDisplayText(query: DataQuery): string {
  22. return JSON.stringify(query);
  23. }
  24. interface Props {
  25. panel: PanelModel;
  26. panelData: PanelData;
  27. onChange: (query: DashboardQuery) => void;
  28. }
  29. type State = {
  30. defaultDatasource: string;
  31. results: ResultInfo[];
  32. };
  33. export class DashboardQueryEditor extends PureComponent<Props, State> {
  34. constructor(props: Props) {
  35. super(props);
  36. this.state = {
  37. defaultDatasource: '',
  38. results: [],
  39. };
  40. }
  41. getQuery(): DashboardQuery {
  42. const { panel } = this.props;
  43. return panel.targets[0] as DashboardQuery;
  44. }
  45. async componentDidMount() {
  46. this.componentDidUpdate(null);
  47. }
  48. async componentDidUpdate(prevProps: Props) {
  49. const { panelData } = this.props;
  50. if (!prevProps || prevProps.panelData !== panelData) {
  51. const query = this.props.panel.targets[0] as DashboardQuery;
  52. const defaultDS = await getDatasourceSrv().get(null);
  53. const dashboard = getDashboardSrv().getCurrent();
  54. const panel = dashboard.getPanelById(query.panelId);
  55. if (!panel) {
  56. this.setState({ defaultDatasource: defaultDS.name });
  57. return;
  58. }
  59. const mainDS = await getDatasourceSrv().get(panel.datasource);
  60. const info: ResultInfo[] = [];
  61. for (const query of panel.targets) {
  62. const ds = query.datasource ? await getDatasourceSrv().get(query.datasource) : mainDS;
  63. const fmt = ds.getQueryDisplayText ? ds.getQueryDisplayText : getQueryDisplayText;
  64. const qData = filterPanelDataToQuery(panelData, query.refId);
  65. const queryData = qData ? qData : panelData;
  66. info.push({
  67. refId: query.refId,
  68. query: fmt(query),
  69. img: ds.meta.info.logos.small,
  70. data: queryData.series,
  71. error: queryData.error,
  72. });
  73. }
  74. this.setState({ defaultDatasource: defaultDS.name, results: info });
  75. }
  76. }
  77. onPanelChanged = (id: number) => {
  78. const { onChange } = this.props;
  79. const query = this.getQuery();
  80. query.panelId = id;
  81. onChange(query);
  82. // Update the
  83. this.props.panel.refresh();
  84. };
  85. renderQueryData(editURL: string) {
  86. const { results } = this.state;
  87. return (
  88. <div>
  89. {results.map((target, index) => {
  90. return (
  91. <div className="query-editor-row__header" key={index}>
  92. <div className="query-editor-row__ref-id">
  93. <img src={target.img} width={16} className={css({ marginRight: '8px' })} />
  94. {target.refId}:
  95. </div>
  96. <div className="query-editor-row__collapsed-text">
  97. <a href={editURL}>
  98. {target.query}
  99. &nbsp;
  100. <i className="fa fa-external-link" />
  101. </a>
  102. </div>
  103. </div>
  104. );
  105. })}
  106. </div>
  107. );
  108. }
  109. getPanelDescription = (panel: PanelModel): string => {
  110. const { defaultDatasource } = this.state;
  111. const dsname = panel.datasource ? panel.datasource : defaultDatasource;
  112. if (panel.targets.length === 1) {
  113. return '1 query to ' + dsname;
  114. }
  115. return panel.targets.length + ' queries to ' + dsname;
  116. };
  117. render() {
  118. const dashboard = getDashboardSrv().getCurrent();
  119. const query = this.getQuery();
  120. let selected: SelectableValue<number>;
  121. const panels: Array<SelectableValue<number>> = [];
  122. for (const panel of dashboard.panels) {
  123. if (panel.targets && panel.datasource !== SHARED_DASHBODARD_QUERY) {
  124. const plugin = config.panels[panel.type];
  125. const item = {
  126. value: panel.id,
  127. label: panel.title ? panel.title : 'Panel ' + panel.id,
  128. description: this.getPanelDescription(panel),
  129. imgUrl: plugin.info.logos.small,
  130. };
  131. panels.push(item);
  132. if (query.panelId === panel.id) {
  133. selected = item;
  134. }
  135. }
  136. }
  137. if (panels.length < 1) {
  138. return (
  139. <div className={css({ padding: '10px' })}>
  140. This dashboard does not have other panels. Add queries to other panels and try again
  141. </div>
  142. );
  143. }
  144. // Same as current URL, but different panelId
  145. const editURL = `d/${dashboard.uid}/${dashboard.title}?&fullscreen&edit&panelId=${query.panelId}`;
  146. return (
  147. <div>
  148. <div className="gf-form">
  149. <div className="gf-form-label">Use results from panel</div>
  150. <Select
  151. placeholder="Choose Panel"
  152. isSearchable={true}
  153. options={panels}
  154. value={selected}
  155. onChange={item => this.onPanelChanged(item.value)}
  156. />
  157. </div>
  158. <div className={css({ padding: '16px' })}>{query.panelId && this.renderQueryData(editURL)}</div>
  159. </div>
  160. );
  161. }
  162. }