aandrew 8 лет назад
Родитель
Сommit
67f0382222

+ 54 - 1
public/app/plugins/panel/table/column_options.html

@@ -69,7 +69,60 @@
       </div>
     </div>
 
-    <div class="section gf-form-group" ng-if="style.type === 'number'">
+    <div class="section gf-form-group" ng-if="style.type === 'string'">
+      <h5 class="section-heading">Mapping</h5>
+      <div class="editor-row">
+        <div class="gf-form-group">
+          <div class="gf-form">
+            <span class="gf-form-label">
+              Type
+            </span>
+            <div class="gf-form-select-wrapper">
+              <select class="gf-form-input" ng-model="style.mappingType"
+                      ng-options="c.value as c.text for c in editor.mappingTypes" ng-change="editor.render()"></select>
+            </div>
+          </div>
+          <div class="gf-form-group" ng-if="style.mappingType==1">
+            <div class="gf-form" ng-repeat="mapping in style.valueMappings">
+              <input type="text" class="gf-form-input width-8" ng-model="mapping.value" placeholder="Value" ng-blur="editor.render()" array-join>
+              <label class="gf-form-label width-3">=></label>
+              <input type="text" class="gf-form-input width-9" ng-model="mapping.text" placeholder="Text" ng-blur="editor.render()" array-join>
+              <label class="gf-form-label">
+                <a class="pointer" tabindex="1" ng-click="editor.removeValueMapping(style, $index)">
+                  <i class="fa fa-trash"></i>
+                </a>
+              </label>
+            </div>
+            <div class="gf-form">
+              <label class="gf-form-label">
+                <a class="pointer" ng-click="editor.addValueMapping(style)"><i class="fa fa-plus"></i></a>
+              </label>
+            </div>
+          </div>
+          <div class="gf-form-group" ng-if="style.mappingType==2">
+            <div class="gf-form" ng-repeat="mapping in style.rangeMappings">
+              <input type="text" class="gf-form-input width-5" ng-model="mapping.from" placeholder="From" ng-blur="editor.render()" array-join>
+              <label class="gf-form-label width-2">-</label>
+              <input type="text" class="gf-form-input width-5" ng-model="mapping.to" placeholder="To" ng-blur="editor.render()" array-join>
+              <label class="gf-form-label width-3">=></label>
+              <input type="text" class="gf-form-input width-5" ng-model="mapping.text" placeholder="Text" ng-blur="editor.render()" array-join>
+              <label class="gf-form-label">
+                <a class="pointer" tabindex="1" ng-click="editor.removeRangeMapping(style, $index)">
+                  <i class="fa fa-trash"></i>
+                </a>
+              </label>
+            </div>
+            <div class="gf-form">
+              <label class="gf-form-label">
+                <a class="pointer" ng-click="editor.addRangeMapping(style)"><i class="fa fa-plus"></i></a>
+              </label>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="section gf-form-group" ng-if="['number', 'string'].indexOf(style.type) !== -1">
       <h5 class="section-heading">Thresholds</h5>
       <div class="gf-form">
         <label class="gf-form-label width-8">Thresholds

+ 28 - 0
public/app/plugins/panel/table/column_options.ts

@@ -13,6 +13,7 @@ export class ColumnOptionsCtrl {
   unitFormats: any;
   getColumnNames: any;
   activeStyleIndex: number;
+  mappingTypes: any;
 
   /** @ngInject */
   constructor($scope) {
@@ -41,6 +42,7 @@ export class ColumnOptionsCtrl {
       { text: 'MM/DD/YY h:mm:ss a', value: 'MM/DD/YY h:mm:ss a' },
       { text: 'MMMM D, YYYY LT', value: 'MMMM D, YYYY LT' },
     ];
+    this.mappingTypes = [{ text: 'Value to text', value: 1 }, { text: 'Range to text', value: 2 }];
 
     this.getColumnNames = () => {
       if (!this.panelCtrl.table) {
@@ -74,6 +76,7 @@ export class ColumnOptionsCtrl {
       pattern: '',
       dateFormat: 'YYYY-MM-DD HH:mm:ss',
       thresholds: [],
+      mappingType: 1,
     };
 
     var styles = this.panel.styles;
@@ -110,6 +113,31 @@ export class ColumnOptionsCtrl {
       this.render();
     };
   }
+  addValueMapping(style) {
+    if (!style.valueMappings) {
+      style.valueMappings = [];
+    }
+    style.valueMappings.push({ value: '', text: '' });
+    this.panelCtrl.render();
+  }
+
+  removeValueMapping(style, index) {
+    style.valueMappings.splice(index, 1);
+    this.panelCtrl.render();
+  }
+
+  removeRangeMapping(style, index) {
+    style.rangeMappings.splice(index, 1);
+    this.panelCtrl.render();
+  }
+
+  addRangeMapping(style) {
+    if (!style.rangeMappings) {
+      style.rangeMappings = [];
+    }
+    style.rangeMappings.push({ from: '', to: '', text: '' });
+    this.panelCtrl.render();
+  }
 }
 
 /** @ngInject */

+ 55 - 1
public/app/plugins/panel/table/renderer.ts

@@ -47,7 +47,7 @@ export class TableRenderer {
     if (!style.thresholds) {
       return null;
     }
-
+    value = Number(value);
     for (var i = style.thresholds.length; i > 0; i--) {
       if (value >= style.thresholds[i - 1]) {
         return style.colors[i];
@@ -100,6 +100,60 @@ export class TableRenderer {
       };
     }
 
+    if (column.style.type === 'string') {
+      return v => {
+        if (column.style.valueMappings && column.style.mappingType && column.style.mappingType === 1) {
+          for (let i = 0; i < column.style.valueMappings.length; i++) {
+            let mapping = column.style.valueMappings[i];
+            var value = Number(mapping.value);
+            if (v === null && mapping.value[0] === 'null') {
+              return mapping.text;
+            }
+            if (v !== null && !_.isArray(v)) {
+              if (Number(v) === value) {
+                if (!_.isString(v) && !_.isArray(v)) {
+                  this.colorState[column.style.colorMode] = this.getColorForValue(v, column.style);
+                }
+                return this.defaultCellFormatter(mapping.text, column.style);
+              }
+            }
+          }
+          if (v !== null && v !== void 0 && !_.isString(v) && !_.isArray(v)) {
+            this.colorState[column.style.colorMode] = this.getColorForValue(v, column.style);
+          }
+        }
+        if (column.style.rangeMappings && column.style.mappingType && column.style.mappingType === 2) {
+          for (let i = 0; i < column.style.rangeMappings.length; i++) {
+            let mapping = column.style.rangeMappings[i];
+            var from = mapping.from;
+            var to = mapping.to;
+            if (v === null && mapping.from[0] === 'null' && mapping.to[0] === 'null') {
+              return mapping.text;
+            }
+            if (
+              v !== null &&
+              !_.isString(v) &&
+              !_.isArray(v) &&
+              from !== '' &&
+              to !== '' &&
+              Number(from[0]) <= v &&
+              Number(to[0]) >= v
+            ) {
+              this.colorState[column.style.colorMode] = this.getColorForValue(v, column.style);
+              return this.defaultCellFormatter(mapping.text, column.style);
+            }
+          }
+          if (v !== null && v !== void 0 && !_.isString(v) && !_.isArray(v)) {
+            this.colorState[column.style.colorMode] = this.getColorForValue(v, column.style);
+          }
+        }
+        if (v === null) {
+          return '-';
+        }
+        return this.defaultCellFormatter(v, column.style);
+      };
+    }
+
     if (column.style.type === 'number') {
       let valueFormatter = kbn.valueFormats[column.unit || column.style.unit];
 

+ 59 - 1
public/app/plugins/panel/table/specs/renderer.jest.ts

@@ -15,8 +15,10 @@ describe('when rendering table', () => {
       { text: 'Sanitized' },
       { text: 'Link' },
       { text: 'Array' },
+      { text: 'Mapping' },
+      { text: 'RangeMapping' },
     ];
-    table.rows = [[1388556366666, 1230, 40, undefined, '', '', 'my.host.com', 'host1', ['value1', 'value2']]];
+    table.rows = [[1388556366666, 1230, 40, undefined, '', '', 'my.host.com', 'host1', ['value1', 'value2'], 1, 2]];
 
     var panel = {
       pageSize: 10,
@@ -47,6 +49,10 @@ describe('when rendering table', () => {
           pattern: 'String',
           type: 'string',
         },
+        {
+          pattern: 'String',
+          type: 'string',
+        },
         {
           pattern: 'United',
           type: 'number',
@@ -72,6 +78,38 @@ describe('when rendering table', () => {
           unit: 'ms',
           decimals: 3,
         },
+        {
+          pattern: 'Mapping',
+          type: 'string',
+          mappingType: 1,
+          valueMappings: [
+            {
+              value: '1',
+              text: 'on',
+            },
+            {
+              value: '0',
+              text: 'off',
+            },
+          ],
+        },
+        {
+          pattern: 'RangeMapping',
+          type: 'string',
+          mappingType: 2,
+          rangeMappings: [
+            {
+              from: '1',
+              to: '3',
+              text: 'on',
+            },
+            {
+              from: '3',
+              to: '6',
+              text: 'off',
+            },
+          ],
+        },
       ],
     };
 
@@ -192,6 +230,26 @@ describe('when rendering table', () => {
       var html = renderer.renderCell(8, 0, ['value1', 'value2']);
       expect(html).toBe('<td>value1, value2</td>');
     });
+
+    it('value should be mapped to text', () => {
+      var html = renderer.renderCell(9, 0, 1);
+      expect(html).toBe('<td>on</td>');
+    });
+
+    it('value should be mapped to text', () => {
+      var html = renderer.renderCell(9, 0, 0);
+      expect(html).toBe('<td>off</td>');
+    });
+
+    it('value should be mapped to text(range)', () => {
+      var html = renderer.renderCell(10, 0, 2);
+      expect(html).toBe('<td>on</td>');
+    });
+
+    it('value should be mapped to text(range)', () => {
+      var html = renderer.renderCell(10, 0, 5);
+      expect(html).toBe('<td>off</td>');
+    });
   });
 });