mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Replace lodash templates with static react renderer for field formatters (#96048)
This commit is contained in:
parent
8ccb0d4ca3
commit
7d0920bbfa
4 changed files with 62 additions and 43 deletions
|
@ -28,10 +28,10 @@ describe('Color Format', () => {
|
|||
|
||||
expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>99</span>');
|
||||
expect(colorer.convert(100, HTML_CONTEXT_TYPE)).toBe(
|
||||
'<span ng-non-bindable><span style="color: blue;background-color: yellow;">100</span></span>'
|
||||
'<span ng-non-bindable><span style="color:blue;background-color:yellow">100</span></span>'
|
||||
);
|
||||
expect(colorer.convert(150, HTML_CONTEXT_TYPE)).toBe(
|
||||
'<span ng-non-bindable><span style="color: blue;background-color: yellow;">150</span></span>'
|
||||
'<span ng-non-bindable><span style="color:blue;background-color:yellow">150</span></span>'
|
||||
);
|
||||
expect(colorer.convert(151, HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>151</span>');
|
||||
});
|
||||
|
@ -74,22 +74,22 @@ describe('Color Format', () => {
|
|||
|
||||
expect(converter('B', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>B</span>');
|
||||
expect(converter('AAA', HTML_CONTEXT_TYPE)).toBe(
|
||||
'<span ng-non-bindable><span style="color: blue;background-color: yellow;">AAA</span></span>'
|
||||
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AAA</span></span>'
|
||||
);
|
||||
expect(converter('AB', HTML_CONTEXT_TYPE)).toBe(
|
||||
'<span ng-non-bindable><span style="color: blue;background-color: yellow;">AB</span></span>'
|
||||
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AB</span></span>'
|
||||
);
|
||||
expect(converter('a', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>a</span>');
|
||||
|
||||
expect(converter('B', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>B</span>');
|
||||
expect(converter('AAA', HTML_CONTEXT_TYPE)).toBe(
|
||||
'<span ng-non-bindable><span style="color: blue;background-color: yellow;">AAA</span></span>'
|
||||
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AAA</span></span>'
|
||||
);
|
||||
expect(converter('AB', HTML_CONTEXT_TYPE)).toBe(
|
||||
'<span ng-non-bindable><span style="color: blue;background-color: yellow;">AB</span></span>'
|
||||
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AB</span></span>'
|
||||
);
|
||||
expect(converter('AB <', HTML_CONTEXT_TYPE)).toBe(
|
||||
'<span ng-non-bindable><span style="color: blue;background-color: yellow;">AB <</span></span>'
|
||||
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AB <</span></span>'
|
||||
);
|
||||
expect(converter('a', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>a</span>');
|
||||
});
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { findLast, cloneDeep, template, escape } from 'lodash';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/server';
|
||||
import { findLast, cloneDeep, escape } from 'lodash';
|
||||
import { KBN_FIELD_TYPES } from '../../kbn_field_types/types';
|
||||
import { FieldFormat } from '../field_format';
|
||||
import { HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types';
|
||||
import { asPrettyString } from '../utils';
|
||||
import { DEFAULT_CONVERTER_COLOR } from '../constants/color_default';
|
||||
|
||||
const convertTemplate = template('<span style="<%- style %>"><%- val %></span>');
|
||||
|
||||
export class ColorFormat extends FieldFormat {
|
||||
static id = FIELD_FORMAT_IDS.COLOR;
|
||||
static title = i18n.translate('data.fieldFormats.color.title', {
|
||||
|
@ -51,11 +51,18 @@ export class ColorFormat extends FieldFormat {
|
|||
|
||||
htmlConvert: HtmlContextTypeConvert = (val) => {
|
||||
const color = this.findColorRuleForVal(val) as typeof DEFAULT_CONVERTER_COLOR;
|
||||
if (!color) return escape(asPrettyString(val));
|
||||
|
||||
let style = '';
|
||||
if (color.text) style += `color: ${color.text};`;
|
||||
if (color.background) style += `background-color: ${color.background};`;
|
||||
return convertTemplate({ val, style });
|
||||
const displayVal = escape(asPrettyString(val));
|
||||
if (!color) return displayVal;
|
||||
|
||||
return ReactDOM.renderToStaticMarkup(
|
||||
<span
|
||||
style={{
|
||||
color: color.text,
|
||||
backgroundColor: color.background,
|
||||
}}
|
||||
dangerouslySetInnerHTML={{ __html: displayVal }} // eslint-disable-line react/no-danger
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
import { SourceFormat } from './source';
|
||||
import { HtmlContextTypeConvert } from '../types';
|
||||
import { HTML_CONTEXT_TYPE } from '../content_types';
|
||||
import { stubIndexPatternWithFields } from '../../index_patterns/index_pattern.stub';
|
||||
|
||||
describe('Source Format', () => {
|
||||
let convertHtml: Function;
|
||||
|
@ -31,4 +32,19 @@ describe('Source Format', () => {
|
|||
'<span ng-non-bindable>{"foo":"bar","number":42,"hello":"<h1>World</h1>","also":"with \\"quotes\\" or 'single quotes'"}</span>'
|
||||
);
|
||||
});
|
||||
|
||||
test('should render a description list if a field is passed', () => {
|
||||
const hit = {
|
||||
foo: 'bar',
|
||||
number: 42,
|
||||
hello: '<h1>World</h1>',
|
||||
also: 'with "quotes" or \'single quotes\'',
|
||||
};
|
||||
|
||||
const indexPattern = { ...stubIndexPatternWithFields, formatHit: (h: string) => h };
|
||||
|
||||
expect(convertHtml(hit, { field: 'field', indexPattern, hit })).toMatchInlineSnapshot(
|
||||
`"<span ng-non-bindable><dl class=\\"source truncate-by-height\\"><dt>foo:</dt><dd>bar</dd> <dt>number:</dt><dd>42</dd> <dt>hello:</dt><dd><h1>World</h1></dd> <dt>also:</dt><dd>with \\"quotes\\" or 'single quotes'</dd> </dl></span>"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,40 +6,34 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { template, escape, keys } from 'lodash';
|
||||
import React, { Fragment } from 'react';
|
||||
import ReactDOM from 'react-dom/server';
|
||||
import { escape, keys } from 'lodash';
|
||||
import { shortenDottedString } from '../../utils';
|
||||
import { KBN_FIELD_TYPES } from '../../kbn_field_types/types';
|
||||
import { FieldFormat } from '../field_format';
|
||||
import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types';
|
||||
import { UI_SETTINGS } from '../../constants';
|
||||
|
||||
/**
|
||||
* Remove all of the whitespace between html tags
|
||||
* so that inline elements don't have extra spaces.
|
||||
*
|
||||
* If you have inline elements (span, a, em, etc.) and any
|
||||
* amount of whitespace around them in your markup, then the
|
||||
* browser will push them apart. This is ugly in certain
|
||||
* scenarios and is only fixed by removing the whitespace
|
||||
* from the html in the first place (or ugly css hacks).
|
||||
*
|
||||
* @param {string} html - the html to modify
|
||||
* @return {string} - modified html
|
||||
*/
|
||||
function noWhiteSpace(html: string) {
|
||||
const TAGS_WITH_WS = />\s+</g;
|
||||
return html.replace(TAGS_WITH_WS, '><');
|
||||
interface Props {
|
||||
defPairs: Array<[string, string]>;
|
||||
}
|
||||
|
||||
const templateHtml = `
|
||||
<dl class="source truncate-by-height">
|
||||
<% defPairs.forEach(function (def) { %>
|
||||
<dt><%- def[0] %>:</dt>
|
||||
<dd><%= def[1] %></dd>
|
||||
<%= ' ' %>
|
||||
<% }); %>
|
||||
</dl>`;
|
||||
const doTemplate = template(noWhiteSpace(templateHtml));
|
||||
const TemplateComponent = ({ defPairs }: Props) => {
|
||||
return (
|
||||
<dl className={'source truncate-by-height'}>
|
||||
{defPairs.map((pair, idx) => (
|
||||
<Fragment key={idx}>
|
||||
<dt
|
||||
dangerouslySetInnerHTML={{ __html: `${escape(pair[0])}:` }} // eslint-disable-line react/no-danger
|
||||
/>
|
||||
<dd
|
||||
dangerouslySetInnerHTML={{ __html: `${pair[1]}` }} // eslint-disable-line react/no-danger
|
||||
/>{' '}
|
||||
</Fragment>
|
||||
))}
|
||||
</dl>
|
||||
);
|
||||
};
|
||||
|
||||
export class SourceFormat extends FieldFormat {
|
||||
static id = FIELD_FORMAT_IDS._SOURCE;
|
||||
|
@ -70,6 +64,8 @@ export class SourceFormat extends FieldFormat {
|
|||
pairs.push([newField, val]);
|
||||
}, []);
|
||||
|
||||
return doTemplate({ defPairs: highlightPairs.concat(sourcePairs) });
|
||||
return ReactDOM.renderToStaticMarkup(
|
||||
<TemplateComponent defPairs={highlightPairs.concat(sourcePairs)} />
|
||||
);
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue