renderer.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. ///<reference path="../../../headers/common.d.ts" />
  2. import _ from 'lodash';
  3. import moment from 'moment';
  4. import kbn from 'app/core/utils/kbn';
  5. export class TableRenderer {
  6. formaters: any[];
  7. colorState: any;
  8. constructor(private panel, private table, private isUtc, private sanitize) {
  9. this.formaters = [];
  10. this.colorState = {};
  11. }
  12. getColorForValue(value, style) {
  13. if (!style.thresholds) { return null; }
  14. for (var i = style.thresholds.length; i > 0; i--) {
  15. if (value >= style.thresholds[i - 1]) {
  16. return style.colors[i];
  17. }
  18. }
  19. return _.first(style.colors);
  20. }
  21. defaultCellFormatter(v, style) {
  22. if (v === null || v === void 0 || v === undefined) {
  23. return '';
  24. }
  25. if (_.isArray(v)) {
  26. v = v.join(', ');
  27. }
  28. if (style && style.sanitize) {
  29. return this.sanitize(v);
  30. } else {
  31. return _.escape(v);
  32. }
  33. }
  34. createColumnFormatter(column) {
  35. if (!column.style) {
  36. return this.defaultCellFormatter;
  37. }
  38. if (column.style.type === 'hidden') {
  39. return v => {
  40. return undefined;
  41. };
  42. }
  43. if (column.style.type === 'date') {
  44. return v => {
  45. if (v === undefined || v === null) {
  46. return '-';
  47. }
  48. if (_.isArray(v)) { v = v[0]; }
  49. var date = moment(v);
  50. if (this.isUtc) {
  51. date = date.utc();
  52. }
  53. return date.format(column.style.dateFormat);
  54. };
  55. }
  56. if (column.style.type === 'number') {
  57. let valueFormatter = kbn.valueFormats[column.unit || column.style.unit];
  58. return v => {
  59. if (v === null || v === void 0) {
  60. return '-';
  61. }
  62. if (_.isString(v)) {
  63. return this.defaultCellFormatter(v, column.style);
  64. }
  65. if (column.style.colorMode) {
  66. this.colorState[column.style.colorMode] = this.getColorForValue(v, column.style);
  67. }
  68. return valueFormatter(v, column.style.decimals, null);
  69. };
  70. }
  71. return (value) => {
  72. return this.defaultCellFormatter(value, column.style);
  73. };
  74. }
  75. formatColumnValue(colIndex, value) {
  76. if (!this.formaters[colIndex]) {
  77. let column = this.table.columns[colIndex];
  78. if (!column.style) {
  79. for (let i = 0; i < this.panel.styles.length; i++) {
  80. let style = this.panel.styles[i];
  81. var regex = kbn.stringToJsRegex(style.pattern);
  82. const matches = column.text.match(regex);
  83. if (matches) {
  84. column.style = style;
  85. if (style.alias) {
  86. column.title = column.text.replace(regex, style.alias);
  87. }
  88. break;
  89. }
  90. }
  91. }
  92. this.formaters[colIndex] = this.createColumnFormatter(column);
  93. }
  94. return this.formaters[colIndex](value);
  95. }
  96. renderCell(columnIndex, value, addWidthHack = false) {
  97. value = this.formatColumnValue(columnIndex, value);
  98. var style = '';
  99. if (this.colorState.cell) {
  100. style = ' style="background-color:' + this.colorState.cell + ';color: white"';
  101. this.colorState.cell = null;
  102. } else if (this.colorState.value) {
  103. style = ' style="color:' + this.colorState.value + '"';
  104. this.colorState.value = null;
  105. }
  106. // because of the fixed table headers css only solution
  107. // there is an issue if header cell is wider the cell
  108. // this hack adds header content to cell (not visible)
  109. var widthHack = '';
  110. if (addWidthHack) {
  111. widthHack = '<div class="table-panel-width-hack">' + this.table.columns[columnIndex].text + '</div>';
  112. }
  113. if (value === undefined) {
  114. style = ' style="display:none;"';
  115. this.table.columns[columnIndex].hidden = true;
  116. } else {
  117. this.table.columns[columnIndex].hidden = false;
  118. }
  119. return '<td' + style + '>' + value + widthHack + '</td>';
  120. }
  121. render(page) {
  122. let pageSize = this.panel.pageSize || 100;
  123. let startPos = page * pageSize;
  124. let endPos = Math.min(startPos + pageSize, this.table.rows.length);
  125. var html = "";
  126. for (var y = startPos; y < endPos; y++) {
  127. let row = this.table.rows[y];
  128. let cellHtml = '';
  129. let rowStyle = '';
  130. for (var i = 0; i < this.table.columns.length; i++) {
  131. cellHtml += this.renderCell(i, row[i], y === startPos);
  132. }
  133. if (this.colorState.row) {
  134. rowStyle = ' style="background-color:' + this.colorState.row + ';color: white"';
  135. this.colorState.row = null;
  136. }
  137. html += '<tr ' + rowStyle + '>' + cellHtml + '</tr>';
  138. }
  139. return html;
  140. }
  141. render_values() {
  142. let rows = [];
  143. for (var y = 0; y < this.table.rows.length; y++) {
  144. let row = this.table.rows[y];
  145. let new_row = [];
  146. for (var i = 0; i < this.table.columns.length; i++) {
  147. new_row.push(this.formatColumnValue(i, row[i]));
  148. }
  149. rows.push(new_row);
  150. }
  151. return {
  152. columns: this.table.columns,
  153. rows: rows,
  154. };
  155. }
  156. }