panel.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Store
  2. import store from 'app/core/store';
  3. // Models
  4. import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
  5. import { PanelModel } from 'app/features/dashboard/state/PanelModel';
  6. import { PanelData, TimeRange, TimeSeries } from '@grafana/ui';
  7. import { TableData } from '@grafana/ui/src';
  8. // Utils
  9. import { isString as _isString } from 'lodash';
  10. import * as rangeUtil from 'app/core/utils/rangeutil';
  11. import * as dateMath from 'app/core/utils/datemath';
  12. import appEvents from 'app/core/app_events';
  13. // Services
  14. import templateSrv from 'app/features/templating/template_srv';
  15. // Constants
  16. import { LS_PANEL_COPY_KEY } from 'app/core/constants';
  17. export const removePanel = (dashboard: DashboardModel, panel: PanelModel, ask: boolean) => {
  18. // confirm deletion
  19. if (ask !== false) {
  20. const text2 = panel.alert ? 'Panel includes an alert rule, removing panel will also remove alert rule' : null;
  21. const confirmText = panel.alert ? 'YES' : null;
  22. appEvents.emit('confirm-modal', {
  23. title: 'Remove Panel',
  24. text: 'Are you sure you want to remove this panel?',
  25. text2: text2,
  26. icon: 'fa-trash',
  27. confirmText: confirmText,
  28. yesText: 'Remove',
  29. onConfirm: () => removePanel(dashboard, panel, false),
  30. });
  31. return;
  32. }
  33. dashboard.removePanel(panel);
  34. };
  35. export const duplicatePanel = (dashboard: DashboardModel, panel: PanelModel) => {
  36. dashboard.duplicatePanel(panel);
  37. };
  38. export const copyPanel = (panel: PanelModel) => {
  39. store.set(LS_PANEL_COPY_KEY, JSON.stringify(panel.getSaveModel()));
  40. appEvents.emit('alert-success', ['Panel copied. Open Add Panel to paste']);
  41. };
  42. const replacePanel = (dashboard: DashboardModel, newPanel: PanelModel, oldPanel: PanelModel) => {
  43. const index = dashboard.panels.findIndex(panel => {
  44. return panel.id === oldPanel.id;
  45. });
  46. const deletedPanel = dashboard.panels.splice(index, 1);
  47. dashboard.events.emit('panel-removed', deletedPanel);
  48. newPanel = new PanelModel(newPanel);
  49. newPanel.id = oldPanel.id;
  50. dashboard.panels.splice(index, 0, newPanel);
  51. dashboard.sortPanelsByGridPos();
  52. dashboard.events.emit('panel-added', newPanel);
  53. };
  54. export const editPanelJson = (dashboard: DashboardModel, panel: PanelModel) => {
  55. const model = {
  56. object: panel.getSaveModel(),
  57. updateHandler: (newPanel: PanelModel, oldPanel: PanelModel) => {
  58. replacePanel(dashboard, newPanel, oldPanel);
  59. },
  60. canUpdate: dashboard.meta.canEdit,
  61. enableCopy: true,
  62. };
  63. appEvents.emit('show-modal', {
  64. src: 'public/app/partials/edit_json.html',
  65. model: model,
  66. });
  67. };
  68. export const sharePanel = (dashboard: DashboardModel, panel: PanelModel) => {
  69. appEvents.emit('show-modal', {
  70. src: 'public/app/features/dashboard/components/ShareModal/template.html',
  71. model: {
  72. dashboard: dashboard,
  73. panel: panel,
  74. },
  75. });
  76. };
  77. export const refreshPanel = (panel: PanelModel) => {
  78. panel.refresh();
  79. };
  80. export const toggleLegend = (panel: PanelModel) => {
  81. console.log('Toggle legend is not implemented yet');
  82. // We need to set panel.legend defaults first
  83. // panel.legend.show = !panel.legend.show;
  84. refreshPanel(panel);
  85. };
  86. export interface TimeOverrideResult {
  87. timeRange: TimeRange;
  88. timeInfo: string;
  89. }
  90. export function applyPanelTimeOverrides(panel: PanelModel, timeRange: TimeRange): TimeOverrideResult {
  91. const newTimeData = {
  92. timeInfo: '',
  93. timeRange: timeRange,
  94. };
  95. if (panel.timeFrom) {
  96. const timeFromInterpolated = templateSrv.replace(panel.timeFrom, panel.scopedVars);
  97. const timeFromInfo = rangeUtil.describeTextRange(timeFromInterpolated);
  98. if (timeFromInfo.invalid) {
  99. newTimeData.timeInfo = 'invalid time override';
  100. return newTimeData;
  101. }
  102. if (_isString(timeRange.raw.from)) {
  103. const timeFromDate = dateMath.parse(timeFromInfo.from);
  104. newTimeData.timeInfo = timeFromInfo.display;
  105. newTimeData.timeRange = {
  106. from: timeFromDate,
  107. to: dateMath.parse(timeFromInfo.to),
  108. raw: {
  109. from: timeFromInfo.from,
  110. to: timeFromInfo.to,
  111. },
  112. };
  113. }
  114. }
  115. if (panel.timeShift) {
  116. const timeShiftInterpolated = templateSrv.replace(panel.timeShift, panel.scopedVars);
  117. const timeShiftInfo = rangeUtil.describeTextRange(timeShiftInterpolated);
  118. if (timeShiftInfo.invalid) {
  119. newTimeData.timeInfo = 'invalid timeshift';
  120. return newTimeData;
  121. }
  122. const timeShift = '-' + timeShiftInterpolated;
  123. newTimeData.timeInfo += ' timeshift ' + timeShift;
  124. const from = dateMath.parseDateMath(timeShift, newTimeData.timeRange.from, false);
  125. const to = dateMath.parseDateMath(timeShift, newTimeData.timeRange.to, true);
  126. newTimeData.timeRange = {
  127. from,
  128. to,
  129. raw: {
  130. from,
  131. to,
  132. },
  133. };
  134. }
  135. if (panel.hideTimeOverride) {
  136. newTimeData.timeInfo = '';
  137. }
  138. return newTimeData;
  139. }
  140. export function getResolution(panel: PanelModel): number {
  141. const htmlEl = document.getElementsByTagName('html')[0];
  142. const width = htmlEl.getBoundingClientRect().width; // https://stackoverflow.com/a/21454625
  143. return panel.maxDataPoints ? panel.maxDataPoints : Math.ceil(width * (panel.gridPos.w / 24));
  144. }
  145. const isTimeSeries = (data: any): data is TimeSeries => data && data.hasOwnProperty('datapoints');
  146. const isTableData = (data: any): data is TableData => data && data.hasOwnProperty('columns');
  147. export const snapshotDataToPanelData = (panel: PanelModel): PanelData => {
  148. const snapshotData = panel.snapshotData;
  149. if (isTimeSeries(snapshotData[0])) {
  150. return {
  151. timeSeries: snapshotData,
  152. } as PanelData;
  153. } else if (isTableData(snapshotData[0])) {
  154. return {
  155. tableData: snapshotData[0],
  156. } as PanelData;
  157. }
  158. throw new Error('snapshotData is invalid:' + snapshotData.toString());
  159. };