renderer.ts 5.0 KB

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