mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(table): added sanitize html option to column styles for table panel, fixes #4596
This commit is contained in:
@@ -12,7 +12,7 @@ func init() {
|
||||
}
|
||||
|
||||
func updateAppDashboards() {
|
||||
time.Sleep(time.Second * 1)
|
||||
time.Sleep(time.Second * 5)
|
||||
|
||||
plog.Debug("Looking for App Dashboard Updates")
|
||||
|
||||
|
||||
@@ -72,6 +72,10 @@
|
||||
Import
|
||||
</a>
|
||||
|
||||
<a class="pull-right small muted" target="_blank" href="https://grafana.net/dashboards?utm_source=grafana_search">
|
||||
Explore ready made dashboards on Grafana.net
|
||||
</a>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<div class="page-header">
|
||||
<h1>Plugins</h1>
|
||||
|
||||
<a class="btn btn-inverse" href="https://grafana.net/plugins?utm_source=grafana_plugin_list" target="_blank">
|
||||
Explore plugins on Grafana.net
|
||||
</a>
|
||||
|
||||
<div class="page-header-tabs">
|
||||
<ul class="gf-tabs">
|
||||
<li class="gf-tabs-item">
|
||||
|
||||
@@ -103,6 +103,11 @@
|
||||
<metric-segment-model property="style.dateFormat" options="editor.dateFormats" on-change="editor.render()" custom="true"></metric-segment-model>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="tight-form-list" ng-if="style.type === 'string'">
|
||||
<li class="tight-form-item">
|
||||
<editor-checkbox text="Sanitize HTML" model="style.sanitize" change="editor.render()"></editor-checkbox>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="tight-form" ng-if="style.type === 'number'">
|
||||
@@ -152,7 +157,7 @@
|
||||
Decimals
|
||||
</li>
|
||||
<li style="width: 105px">
|
||||
<input type="number" class="input-mini tight-form-input" ng-model="style.decimals" ng-change="render()" ng-model-onblur>
|
||||
<input type="number" class="input-mini tight-form-input" ng-model="style.decimals" ng-change="editor.render()" ng-model-onblur>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
@@ -45,7 +45,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
|
||||
};
|
||||
|
||||
/** @ngInject */
|
||||
constructor($scope, $injector, private annotationsSrv) {
|
||||
constructor($scope, $injector, private annotationsSrv, private $sanitize) {
|
||||
super($scope, $injector);
|
||||
this.pageIndex = 0;
|
||||
|
||||
@@ -159,7 +159,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
|
||||
}
|
||||
|
||||
function appendTableRows(tbodyElem) {
|
||||
var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc());
|
||||
var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc(), ctrl.$sanitize);
|
||||
tbodyElem.empty();
|
||||
tbodyElem.html(renderer.render(ctrl.pageIndex));
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export class TableRenderer {
|
||||
formaters: any[];
|
||||
colorState: any;
|
||||
|
||||
constructor(private panel, private table, private isUtc) {
|
||||
constructor(private panel, private table, private isUtc, private sanitize) {
|
||||
this.formaters = [];
|
||||
this.colorState = {};
|
||||
}
|
||||
@@ -24,7 +24,7 @@ export class TableRenderer {
|
||||
return _.first(style.colors);
|
||||
}
|
||||
|
||||
defaultCellFormater(v) {
|
||||
defaultCellFormater(v, style) {
|
||||
if (v === null || v === void 0 || v === undefined) {
|
||||
return '';
|
||||
}
|
||||
@@ -33,7 +33,11 @@ export class TableRenderer {
|
||||
v = v.join(', ');
|
||||
}
|
||||
|
||||
return v;
|
||||
if (style && style.sanitize) {
|
||||
return this.sanitize(v);
|
||||
} else {
|
||||
return _.escape(v);
|
||||
}
|
||||
}
|
||||
|
||||
createColumnFormater(style, column) {
|
||||
@@ -61,7 +65,7 @@ export class TableRenderer {
|
||||
}
|
||||
|
||||
if (_.isString(v)) {
|
||||
return v;
|
||||
return this.defaultCellFormater(v, style);
|
||||
}
|
||||
|
||||
if (style.colorMode) {
|
||||
@@ -72,7 +76,9 @@ export class TableRenderer {
|
||||
};
|
||||
}
|
||||
|
||||
return this.defaultCellFormater;
|
||||
return (value) => {
|
||||
return this.defaultCellFormater(value, style);
|
||||
};
|
||||
}
|
||||
|
||||
formatColumnValue(colIndex, value) {
|
||||
@@ -96,7 +102,6 @@ export class TableRenderer {
|
||||
|
||||
renderCell(columnIndex, value, addWidthHack = false) {
|
||||
value = this.formatColumnValue(columnIndex, value);
|
||||
value = _.escape(value);
|
||||
var style = '';
|
||||
if (this.colorState.cell) {
|
||||
style = ' style="background-color:' + this.colorState.cell + ';color: white"';
|
||||
|
||||
@@ -13,6 +13,7 @@ describe('when rendering table', () => {
|
||||
{text: 'Undefined'},
|
||||
{text: 'String'},
|
||||
{text: 'United', unit: 'bps'},
|
||||
{text: 'Sanitized'},
|
||||
];
|
||||
|
||||
var panel = {
|
||||
@@ -47,11 +48,20 @@ describe('when rendering table', () => {
|
||||
type: 'number',
|
||||
unit: 'ms',
|
||||
decimals: 2,
|
||||
},
|
||||
{
|
||||
pattern: 'Sanitized',
|
||||
type: 'string',
|
||||
sanitize: true,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var renderer = new TableRenderer(panel, table, 'utc');
|
||||
var sanitize = function(value) {
|
||||
return 'sanitized';
|
||||
};
|
||||
|
||||
var renderer = new TableRenderer(panel, table, 'utc', sanitize);
|
||||
|
||||
it('time column should be formated', () => {
|
||||
var html = renderer.renderCell(0, 1388556366666);
|
||||
@@ -107,6 +117,11 @@ describe('when rendering table', () => {
|
||||
var html = renderer.renderCell(3, undefined);
|
||||
expect(html).to.be('<td></td>');
|
||||
});
|
||||
|
||||
it('sanitized value should render as', () => {
|
||||
var html = renderer.renderCell(6, 'text <a href="http://google.com">link</a>');
|
||||
expect(html).to.be('<td>sanitized</td>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
|
||||
.search-button-row {
|
||||
padding-top: 20px;
|
||||
line-height: 2.5rem;
|
||||
button, a {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user