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() {
|
func updateAppDashboards() {
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 5)
|
||||||
|
|
||||||
plog.Debug("Looking for App Dashboard Updates")
|
plog.Debug("Looking for App Dashboard Updates")
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,10 @@
|
|||||||
Import
|
Import
|
||||||
</a>
|
</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 class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>Plugins</h1>
|
<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">
|
<div class="page-header-tabs">
|
||||||
<ul class="gf-tabs">
|
<ul class="gf-tabs">
|
||||||
<li class="gf-tabs-item">
|
<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>
|
<metric-segment-model property="style.dateFormat" options="editor.dateFormats" on-change="editor.render()" custom="true"></metric-segment-model>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</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 class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tight-form" ng-if="style.type === 'number'">
|
<div class="tight-form" ng-if="style.type === 'number'">
|
||||||
@@ -152,7 +157,7 @@
|
|||||||
Decimals
|
Decimals
|
||||||
</li>
|
</li>
|
||||||
<li style="width: 105px">
|
<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>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor($scope, $injector, private annotationsSrv) {
|
constructor($scope, $injector, private annotationsSrv, private $sanitize) {
|
||||||
super($scope, $injector);
|
super($scope, $injector);
|
||||||
this.pageIndex = 0;
|
this.pageIndex = 0;
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function appendTableRows(tbodyElem) {
|
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.empty();
|
||||||
tbodyElem.html(renderer.render(ctrl.pageIndex));
|
tbodyElem.html(renderer.render(ctrl.pageIndex));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export class TableRenderer {
|
|||||||
formaters: any[];
|
formaters: any[];
|
||||||
colorState: any;
|
colorState: any;
|
||||||
|
|
||||||
constructor(private panel, private table, private isUtc) {
|
constructor(private panel, private table, private isUtc, private sanitize) {
|
||||||
this.formaters = [];
|
this.formaters = [];
|
||||||
this.colorState = {};
|
this.colorState = {};
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ export class TableRenderer {
|
|||||||
return _.first(style.colors);
|
return _.first(style.colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultCellFormater(v) {
|
defaultCellFormater(v, style) {
|
||||||
if (v === null || v === void 0 || v === undefined) {
|
if (v === null || v === void 0 || v === undefined) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,11 @@ export class TableRenderer {
|
|||||||
v = v.join(', ');
|
v = v.join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
if (style && style.sanitize) {
|
||||||
|
return this.sanitize(v);
|
||||||
|
} else {
|
||||||
|
return _.escape(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createColumnFormater(style, column) {
|
createColumnFormater(style, column) {
|
||||||
@@ -61,7 +65,7 @@ export class TableRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_.isString(v)) {
|
if (_.isString(v)) {
|
||||||
return v;
|
return this.defaultCellFormater(v, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style.colorMode) {
|
if (style.colorMode) {
|
||||||
@@ -72,7 +76,9 @@ export class TableRenderer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.defaultCellFormater;
|
return (value) => {
|
||||||
|
return this.defaultCellFormater(value, style);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
formatColumnValue(colIndex, value) {
|
formatColumnValue(colIndex, value) {
|
||||||
@@ -96,7 +102,6 @@ export class TableRenderer {
|
|||||||
|
|
||||||
renderCell(columnIndex, value, addWidthHack = false) {
|
renderCell(columnIndex, value, addWidthHack = false) {
|
||||||
value = this.formatColumnValue(columnIndex, value);
|
value = this.formatColumnValue(columnIndex, value);
|
||||||
value = _.escape(value);
|
|
||||||
var style = '';
|
var style = '';
|
||||||
if (this.colorState.cell) {
|
if (this.colorState.cell) {
|
||||||
style = ' style="background-color:' + this.colorState.cell + ';color: white"';
|
style = ' style="background-color:' + this.colorState.cell + ';color: white"';
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ describe('when rendering table', () => {
|
|||||||
{text: 'Undefined'},
|
{text: 'Undefined'},
|
||||||
{text: 'String'},
|
{text: 'String'},
|
||||||
{text: 'United', unit: 'bps'},
|
{text: 'United', unit: 'bps'},
|
||||||
|
{text: 'Sanitized'},
|
||||||
];
|
];
|
||||||
|
|
||||||
var panel = {
|
var panel = {
|
||||||
@@ -47,11 +48,20 @@ describe('when rendering table', () => {
|
|||||||
type: 'number',
|
type: 'number',
|
||||||
unit: 'ms',
|
unit: 'ms',
|
||||||
decimals: 2,
|
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', () => {
|
it('time column should be formated', () => {
|
||||||
var html = renderer.renderCell(0, 1388556366666);
|
var html = renderer.renderCell(0, 1388556366666);
|
||||||
@@ -107,6 +117,11 @@ describe('when rendering table', () => {
|
|||||||
var html = renderer.renderCell(3, undefined);
|
var html = renderer.renderCell(3, undefined);
|
||||||
expect(html).to.be('<td></td>');
|
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 {
|
.search-button-row {
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
|
line-height: 2.5rem;
|
||||||
button, a {
|
button, a {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user