panel.ts 4.9 KB

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