time_region_manager.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import 'vendor/flot/jquery.flot';
  2. import { map } from 'lodash';
  3. import { dateTime, DateTime, AbsoluteTimeRange, GrafanaTheme } from '@grafana/data';
  4. import { config } from 'app/core/config';
  5. type TimeRegionColorDefinition = {
  6. fill: string | null;
  7. line: string | null;
  8. };
  9. export const colorModes: any = {
  10. gray: {
  11. themeDependent: true,
  12. title: 'Gray',
  13. darkColor: { fill: 'rgba(255, 255, 255, 0.09)', line: 'rgba(255, 255, 255, 0.2)' },
  14. lightColor: { fill: 'rgba(0, 0, 0, 0.09)', line: 'rgba(0, 0, 0, 0.2)' },
  15. },
  16. red: {
  17. title: 'Red',
  18. color: { fill: 'rgba(234, 112, 112, 0.12)', line: 'rgba(237, 46, 24, 0.60)' },
  19. },
  20. green: {
  21. title: 'Green',
  22. color: { fill: 'rgba(11, 237, 50, 0.090)', line: 'rgba(6,163,69, 0.60)' },
  23. },
  24. blue: {
  25. title: 'Blue',
  26. color: { fill: 'rgba(11, 125, 238, 0.12)', line: 'rgba(11, 125, 238, 0.60)' },
  27. },
  28. yellow: {
  29. title: 'Yellow',
  30. color: { fill: 'rgba(235, 138, 14, 0.12)', line: 'rgba(247, 149, 32, 0.60)' },
  31. },
  32. custom: { title: 'Custom' },
  33. };
  34. export function getColorModes() {
  35. return map(Object.keys(colorModes), (key) => {
  36. return {
  37. key,
  38. value: colorModes[key].title,
  39. };
  40. });
  41. }
  42. function getColor(timeRegion: any, theme: GrafanaTheme): TimeRegionColorDefinition {
  43. if (Object.keys(colorModes).indexOf(timeRegion.colorMode) === -1) {
  44. timeRegion.colorMode = 'red';
  45. }
  46. if (timeRegion.colorMode === 'custom') {
  47. return {
  48. fill: timeRegion.fill && timeRegion.fillColor ? theme.visualization.getColorByName(timeRegion.fillColor) : null,
  49. line: timeRegion.line && timeRegion.lineColor ? theme.visualization.getColorByName(timeRegion.lineColor) : null,
  50. };
  51. }
  52. const colorMode = colorModes[timeRegion.colorMode];
  53. if (colorMode.themeDependent === true) {
  54. return theme.isLight ? colorMode.lightColor : colorMode.darkColor;
  55. }
  56. return {
  57. fill: timeRegion.fill ? theme.visualization.getColorByName(colorMode.color.fill) : null,
  58. line: timeRegion.fill ? theme.visualization.getColorByName(colorMode.color.line) : null,
  59. };
  60. }
  61. export class TimeRegionManager {
  62. plot: any;
  63. timeRegions: any;
  64. constructor(private panelCtrl: any) {}
  65. draw(plot: any) {
  66. this.timeRegions = this.panelCtrl.panel.timeRegions;
  67. this.plot = plot;
  68. }
  69. addFlotOptions(options: any, panel: any) {
  70. if (!panel.timeRegions || panel.timeRegions.length === 0) {
  71. return;
  72. }
  73. const tRange = {
  74. from: dateTime(this.panelCtrl.range.from).utc(),
  75. to: dateTime(this.panelCtrl.range.to).utc(),
  76. };
  77. let i: number,
  78. hRange: { from: any; to: any },
  79. timeRegion: any,
  80. regions: AbsoluteTimeRange[],
  81. fromStart: DateTime,
  82. fromEnd: DateTime,
  83. timeRegionColor: TimeRegionColorDefinition;
  84. const timeRegionsCopy = panel.timeRegions.map((a: any) => ({ ...a }));
  85. for (i = 0; i < timeRegionsCopy.length; i++) {
  86. timeRegion = timeRegionsCopy[i];
  87. if (!(timeRegion.fromDayOfWeek || timeRegion.from) && !(timeRegion.toDayOfWeek || timeRegion.to)) {
  88. continue;
  89. }
  90. if (timeRegion.from && !timeRegion.to) {
  91. timeRegion.to = timeRegion.from;
  92. }
  93. if (!timeRegion.from && timeRegion.to) {
  94. timeRegion.from = timeRegion.to;
  95. }
  96. hRange = {
  97. from: this.parseTimeRange(timeRegion.from),
  98. to: this.parseTimeRange(timeRegion.to),
  99. };
  100. if (!timeRegion.fromDayOfWeek && timeRegion.toDayOfWeek) {
  101. timeRegion.fromDayOfWeek = timeRegion.toDayOfWeek;
  102. }
  103. if (!timeRegion.toDayOfWeek && timeRegion.fromDayOfWeek) {
  104. timeRegion.toDayOfWeek = timeRegion.fromDayOfWeek;
  105. }
  106. if (timeRegion.fromDayOfWeek) {
  107. hRange.from.dayOfWeek = Number(timeRegion.fromDayOfWeek);
  108. }
  109. if (timeRegion.toDayOfWeek) {
  110. hRange.to.dayOfWeek = Number(timeRegion.toDayOfWeek);
  111. }
  112. if (hRange.from.dayOfWeek && hRange.from.h === null && hRange.from.m === null) {
  113. hRange.from.h = 0;
  114. hRange.from.m = 0;
  115. hRange.from.s = 0;
  116. }
  117. if (hRange.to.dayOfWeek && hRange.to.h === null && hRange.to.m === null) {
  118. hRange.to.h = 23;
  119. hRange.to.m = 59;
  120. hRange.to.s = 59;
  121. }
  122. if (!hRange.from || !hRange.to) {
  123. continue;
  124. }
  125. regions = [];
  126. fromStart = dateTime(tRange.from);
  127. fromStart.set('hour', 0);
  128. fromStart.set('minute', 0);
  129. fromStart.set('second', 0);
  130. fromStart.add(hRange.from.h, 'hours');
  131. fromStart.add(hRange.from.m, 'minutes');
  132. fromStart.add(hRange.from.s, 'seconds');
  133. while (fromStart.unix() <= tRange.to.unix()) {
  134. while (hRange.from.dayOfWeek && hRange.from.dayOfWeek !== fromStart.isoWeekday()) {
  135. fromStart.add(24, 'hours');
  136. }
  137. if (fromStart.unix() > tRange.to.unix()) {
  138. break;
  139. }
  140. fromEnd = dateTime(fromStart);
  141. if (fromEnd.hour) {
  142. if (hRange.from.h <= hRange.to.h) {
  143. fromEnd.add(hRange.to.h - hRange.from.h, 'hours');
  144. } else if (hRange.from.h > hRange.to.h) {
  145. while (fromEnd.hour() !== hRange.to.h) {
  146. fromEnd.add(1, 'hours');
  147. }
  148. } else {
  149. fromEnd.add(24 - hRange.from.h, 'hours');
  150. while (fromEnd.hour() !== hRange.to.h) {
  151. fromEnd.add(1, 'hours');
  152. }
  153. }
  154. }
  155. fromEnd.set('minute', hRange.to.m);
  156. fromEnd.set('second', hRange.to.s);
  157. while (hRange.to.dayOfWeek && hRange.to.dayOfWeek !== fromEnd.isoWeekday()) {
  158. fromEnd.add(24, 'hours');
  159. }
  160. const outsideRange =
  161. (fromStart.unix() < tRange.from.unix() && fromEnd.unix() < tRange.from.unix()) ||
  162. (fromStart.unix() > tRange.to.unix() && fromEnd.unix() > tRange.to.unix());
  163. if (!outsideRange) {
  164. regions.push({ from: fromStart.valueOf(), to: fromEnd.valueOf() });
  165. }
  166. fromStart.add(24, 'hours');
  167. }
  168. timeRegionColor = getColor(timeRegion, config.theme);
  169. for (let j = 0; j < regions.length; j++) {
  170. const r = regions[j];
  171. if (timeRegion.fill) {
  172. options.grid.markings.push({
  173. xaxis: { from: r.from, to: r.to },
  174. color: timeRegionColor.fill,
  175. });
  176. }
  177. if (timeRegion.line) {
  178. options.grid.markings.push({
  179. xaxis: { from: r.from, to: r.from },
  180. color: timeRegionColor.line,
  181. });
  182. options.grid.markings.push({
  183. xaxis: { from: r.to, to: r.to },
  184. color: timeRegionColor.line,
  185. });
  186. }
  187. }
  188. }
  189. }
  190. parseTimeRange(str: string) {
  191. const timeRegex = /^([\d]+):?(\d{2})?/;
  192. const result: any = { h: null, m: null };
  193. const match = timeRegex.exec(str);
  194. if (!match) {
  195. return result;
  196. }
  197. if (match.length > 1) {
  198. result.h = Number(match[1]);
  199. result.m = 0;
  200. if (match.length > 2 && match[2] !== undefined) {
  201. result.m = Number(match[2]);
  202. }
  203. if (result.h > 23) {
  204. result.h = 23;
  205. }
  206. if (result.m > 59) {
  207. result.m = 59;
  208. }
  209. }
  210. return result;
  211. }
  212. }