Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.x] Display changed field formats without requiring hard page refresh. (#53746) #53771

Merged
merged 1 commit into from
Dec 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import { memoize, noop } from 'lodash';
import moment from 'moment-timezone';
import { KBN_FIELD_TYPES } from '../../kbn_field_types/types';
import { FieldFormat } from '../field_format';
import { FieldFormat, IFieldFormatMetaParams } from '../field_format';
import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types';

export class DateFormat extends FieldFormat {
Expand All @@ -32,7 +32,7 @@ export class DateFormat extends FieldFormat {
private memoizedPattern: string = '';
private timeZone: string = '';

constructor(params: Record<string, any>, getConfig: Function) {
constructor(params: IFieldFormatMetaParams, getConfig: Function) {
super(params, getConfig);

this.memoizedConverter = memoize((val: any) => {
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/common/field_formats/converters/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { escape, memoize } from 'lodash';
import { getHighlightHtml } from '../utils';
import { KBN_FIELD_TYPES } from '../../kbn_field_types/types';
import { FieldFormat } from '../field_format';
import { FieldFormat, IFieldFormatMetaParams } from '../field_format';
import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types';

const templateMatchRE = /{{([\s\S]+?)}}/g;
Expand Down Expand Up @@ -64,7 +64,7 @@ export class UrlFormat extends FieldFormat {
];
static urlTypes = URL_TYPES;

constructor(params: Record<string, any>) {
constructor(params: IFieldFormatMetaParams) {
super(params);
this.compileTemplate = memoize(this.compileTemplate);
}
Expand Down
11 changes: 10 additions & 1 deletion src/plugins/data/common/field_formats/field_format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ import { HtmlContextTypeConvert, TextContextTypeConvert } from './types';

const DEFAULT_CONTEXT_TYPE = TEXT_CONTEXT_TYPE;

export interface IFieldFormatMetaParams {
[key: string]: any;
parsedUrl?: {
origin: string;
pathname?: string;
basePath?: string;
};
}

export abstract class FieldFormat {
/**
* @property {string} - Field Format Id
Expand Down Expand Up @@ -90,7 +99,7 @@ export abstract class FieldFormat {
protected readonly _params: any;
protected getConfig: Function | undefined;

constructor(_params: Record<string, any> = {}, getConfig?: Function) {
constructor(_params: IFieldFormatMetaParams = {}, getConfig?: Function) {
this._params = _params;

if (getConfig) {
Expand Down
7 changes: 6 additions & 1 deletion src/plugins/data/common/field_formats/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
*/

export { HTML_CONTEXT_TYPE, TEXT_CONTEXT_TYPE } from './content_types';
export { FieldFormat, IFieldFormatType, IFieldFormatId } from './field_format';
export {
FieldFormat,
IFieldFormatType,
IFieldFormatId,
IFieldFormatMetaParams,
} from './field_format';
export { getHighlightRequest, asPrettyString, getHighlightHtml } from './utils';
export * from './converters';
export * from './constants';
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import { CoreSetup, IUiSettingsClient } from 'kibana/public';

import { FieldFormatRegisty } from './field_formats';
import {
BoolFormat,
IFieldFormatType,
PercentFormat,
BoolFormat,
StringFormat,
} from '../../common/field_formats';
import { coreMock } from '../../../../core/public/mocks';
import { KBN_FIELD_TYPES } from '../../common';

const getValueOfPrivateField = (instance: any, field: string) => instance[field];
const getUiSettingsMock = (data: any): IUiSettingsClient['get'] => () => data;
Expand Down Expand Up @@ -115,12 +116,12 @@ describe('FieldFormatRegisty', () => {
test('should set meta params for all instances of FieldFormats', () => {
fieldFormatRegisty.register([StringFormat]);

const ConcreteFormat = fieldFormatRegisty.getType(StringFormat.id);
const DecoratedStingFormat = fieldFormatRegisty.getType(StringFormat.id);

expect(ConcreteFormat).toBeDefined();
expect(DecoratedStingFormat).toBeDefined();

if (ConcreteFormat) {
const stringFormat = new ConcreteFormat({
if (DecoratedStingFormat) {
const stringFormat = new DecoratedStingFormat({
foo: 'foo',
});
const params = getValueOfPrivateField(stringFormat, '_params');
Expand All @@ -132,5 +133,39 @@ describe('FieldFormatRegisty', () => {
expect(params.parsedUrl).toHaveProperty('basePath');
}
});

test('should decorate static fields', () => {
fieldFormatRegisty.register([BoolFormat]);

const DecoratedBoolFormat = fieldFormatRegisty.getType(BoolFormat.id);

expect(DecoratedBoolFormat).toBeDefined();

if (DecoratedBoolFormat) {
expect(DecoratedBoolFormat.id).toBe(BoolFormat.id);
expect(DecoratedBoolFormat.fieldType).toBe(BoolFormat.fieldType);
}
});
});

describe('getByFieldType', () => {
test('should provide an public "getByFieldType" method', () => {
expect(fieldFormatRegisty.getByFieldType).toBeDefined();
expect(typeof fieldFormatRegisty.getByFieldType).toBe('function');
});

test('should decorate returns types', () => {
fieldFormatRegisty.register([StringFormat, BoolFormat]);

const [DecoratedStringFormat] = fieldFormatRegisty.getByFieldType(KBN_FIELD_TYPES.STRING);

expect(DecoratedStringFormat).toBeDefined();

const stingFormat = new DecoratedStringFormat({ foo: 'foo' });
const params = getValueOfPrivateField(stingFormat, '_params');

expect(params).toHaveProperty('foo');
expect(params).toHaveProperty('parsedUrl');
});
});
});
84 changes: 56 additions & 28 deletions src/plugins/data/public/field_formats_provider/field_formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/

// eslint-disable-next-line max-classes-per-file
import { forOwn, isFunction, memoize } from 'lodash';
import { IUiSettingsClient, CoreSetup } from 'kibana/public';
import {
Expand All @@ -26,6 +27,7 @@ import {
IFieldFormatType,
IFieldFormatId,
FieldFormat,
IFieldFormatMetaParams,
} from '../../common';
import { FieldType } from './types';

Expand Down Expand Up @@ -75,14 +77,20 @@ export class FieldFormatRegisty {
* Get a derived FieldFormat class by its id.
*
* @param {IFieldFormatId} formatId - the format id
* @return {FieldFormat | void}
* @return {FieldFormat | undefined}
*/
getType = (formatId: IFieldFormatId): IFieldFormatType | void => {
const decoratedFieldFormat: any = this.fieldFormatMetaParamsDecorator(formatId);
getType = (formatId: IFieldFormatId): IFieldFormatType | undefined => {
const fieldFormat = this.fieldFormats.get(formatId);

if (decoratedFieldFormat) {
return decoratedFieldFormat as IFieldFormatType;
if (fieldFormat) {
const decoratedFieldFormat: any = this.fieldFormatMetaParamsDecorator(fieldFormat);

if (decoratedFieldFormat) {
return decoratedFieldFormat as IFieldFormatType;
}
}

return undefined;
};

/**
Expand All @@ -92,12 +100,12 @@ export class FieldFormatRegisty {
*
* @param {KBN_FIELD_TYPES} fieldType
* @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types
* @return {FieldFormat | void}
* @return {FieldFormat | undefined}
*/
getDefaultType = (
fieldType: KBN_FIELD_TYPES,
esTypes: ES_FIELD_TYPES[]
): IFieldFormatType | void => {
): IFieldFormatType | undefined => {
const config = this.getDefaultConfig(fieldType, esTypes);

return this.getType(config.id);
Expand All @@ -108,11 +116,11 @@ export class FieldFormatRegisty {
* using the format:defaultTypeMap config map
*
* @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types
* @return {ES_FIELD_TYPES | void}
* @return {ES_FIELD_TYPES | undefined}
*/
getTypeNameByEsTypes = (esTypes: ES_FIELD_TYPES[] | undefined): ES_FIELD_TYPES | void => {
getTypeNameByEsTypes = (esTypes: ES_FIELD_TYPES[] | undefined): ES_FIELD_TYPES | undefined => {
if (!Array.isArray(esTypes)) {
return;
return undefined;
}

return esTypes.find(type => this.defaultMap[type] && this.defaultMap[type].es);
Expand Down Expand Up @@ -196,9 +204,12 @@ export class FieldFormatRegisty {
* @return {FieldFormat[]}
*/
getByFieldType(fieldType: KBN_FIELD_TYPES): IFieldFormatType[] {
return [...this.fieldFormats.values()].filter(
(format: IFieldFormatType) => format.fieldType.indexOf(fieldType) !== -1
);
return [...this.fieldFormats.values()]
.filter((format: IFieldFormatType) => format && format.fieldType.indexOf(fieldType) !== -1)
.map(
(format: IFieldFormatType) =>
this.fieldFormatMetaParamsDecorator(format) as IFieldFormatType
);
}

/**
Expand Down Expand Up @@ -232,24 +243,41 @@ export class FieldFormatRegisty {
* FieldFormat decorator - provide a one way to add meta-params for all field formatters
*
* @private
* @param {IFieldFormatId} formatId - the format id
* @return {FieldFormat | void}
* @param {IFieldFormatType} fieldFormat - field format type
* @return {FieldFormat | undefined}
*/
private fieldFormatMetaParamsDecorator = (formatId: IFieldFormatId): Function | void => {
const concreteFieldFormat = this.fieldFormats.get(formatId);
const decorateMetaParams = (customOptions: Record<string, any> = {}) => ({
parsedUrl: {
origin: window.location.origin,
pathname: window.location.pathname,
basePath: this.basePath,
},
...customOptions,
});
private fieldFormatMetaParamsDecorator = (
fieldFormat: IFieldFormatType
): IFieldFormatType | undefined => {
const getMetaParams = (customParams: Record<string, any>) => this.buildMetaParams(customParams);

if (concreteFieldFormat) {
return function(params: Record<string, any> = {}, getConfig?: Function) {
return new concreteFieldFormat(decorateMetaParams(params), getConfig);
if (fieldFormat) {
return class DecoratedFieldFormat extends fieldFormat {
static id = fieldFormat.id;
static fieldType = fieldFormat.fieldType;

constructor(params: Record<string, any> = {}, getConfig?: Function) {
super(getMetaParams(params), getConfig);
}
};
}

return undefined;
};

/**
* Build Meta Params
*
* @static
* @param {Record<string, any>} custom params
* @return {Record<string, any>}
*/
private buildMetaParams = <T extends IFieldFormatMetaParams>(customParams: T): T => ({
parsedUrl: {
origin: window.location.origin,
pathname: window.location.pathname,
basePath: this.basePath,
},
...customParams,
});
}