From e4839da54d6dd232a024ca67bc37f1ea3a488344 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Sat, 21 Dec 2019 16:11:04 +0300 Subject: [PATCH 1/3] Display changed field formats without requiring hard page refresh. --- .../field_formats.test.ts | 45 +++++++++++-- .../field_formats_provider/field_formats.ts | 63 +++++++++++++------ 2 files changed, 83 insertions(+), 25 deletions(-) diff --git a/src/plugins/data/public/field_formats_provider/field_formats.test.ts b/src/plugins/data/public/field_formats_provider/field_formats.test.ts index e58435fc71418..8ad6cff77abc0 100644 --- a/src/plugins/data/public/field_formats_provider/field_formats.test.ts +++ b/src/plugins/data/public/field_formats_provider/field_formats.test.ts @@ -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; @@ -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'); @@ -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'); + }); }); }); diff --git a/src/plugins/data/public/field_formats_provider/field_formats.ts b/src/plugins/data/public/field_formats_provider/field_formats.ts index 3d60965f2e532..15fd690dc4736 100644 --- a/src/plugins/data/public/field_formats_provider/field_formats.ts +++ b/src/plugins/data/public/field_formats_provider/field_formats.ts @@ -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 { @@ -78,10 +79,14 @@ export class FieldFormatRegisty { * @return {FieldFormat | void} */ getType = (formatId: IFieldFormatId): IFieldFormatType | void => { - const decoratedFieldFormat: any = this.fieldFormatMetaParamsDecorator(formatId); + 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; + } } }; @@ -196,9 +201,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 + ); } /** @@ -232,24 +240,39 @@ export class FieldFormatRegisty { * FieldFormat decorator - provide a one way to add meta-params for all field formatters * * @private - * @param {IFieldFormatId} formatId - the format id + * @param {IFieldFormatType} fieldFormat - field format type * @return {FieldFormat | void} */ - private fieldFormatMetaParamsDecorator = (formatId: IFieldFormatId): Function | void => { - const concreteFieldFormat = this.fieldFormats.get(formatId); - const decorateMetaParams = (customOptions: Record = {}) => ({ - parsedUrl: { - origin: window.location.origin, - pathname: window.location.pathname, - basePath: this.basePath, - }, - ...customOptions, - }); + private fieldFormatMetaParamsDecorator = ( + fieldFormat: IFieldFormatType + ): IFieldFormatType | void => { + const getMetaParams = (customParams: Record) => this.buildMetaParams(customParams); - if (concreteFieldFormat) { - return function(params: Record = {}, 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 = {}, getConfig?: Function) { + super(getMetaParams(params), getConfig); + } }; } }; + + /** + * Build Meta Params + * + * @static + * @param {Record} custom params + * @return {Record} + */ + private buildMetaParams = (customParams: Record = {}): Record => ({ + parsedUrl: { + origin: window.location.origin, + pathname: window.location.pathname, + basePath: this.basePath, + }, + ...customParams, + }); } From acbba4a48ecd8154c809a0245d9e65de75be5553 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 23 Dec 2019 15:06:50 +0300 Subject: [PATCH 2/3] Update src/plugins/data/public/field_formats_provider/field_formats.ts Co-Authored-By: Vadim Dalecky --- src/plugins/data/public/field_formats_provider/field_formats.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/public/field_formats_provider/field_formats.ts b/src/plugins/data/public/field_formats_provider/field_formats.ts index 15fd690dc4736..38a29de1e2d58 100644 --- a/src/plugins/data/public/field_formats_provider/field_formats.ts +++ b/src/plugins/data/public/field_formats_provider/field_formats.ts @@ -267,7 +267,7 @@ export class FieldFormatRegisty { * @param {Record} custom params * @return {Record} */ - private buildMetaParams = (customParams: Record = {}): Record => ({ + private buildMetaParams = (customParams: T = {}): T & {parsedUrl: ParsedUrl} => ({ parsedUrl: { origin: window.location.origin, pathname: window.location.pathname, From 3f07abac6e8b9342b95e4612f0b73e2d22a2503d Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 23 Dec 2019 15:47:09 +0300 Subject: [PATCH 3/3] fix PR commetns --- .../field_formats/converters/date_server.ts | 4 +-- .../common/field_formats/converters/url.ts | 4 +-- .../data/common/field_formats/field_format.ts | 11 +++++++- .../data/common/field_formats/index.ts | 7 +++++- .../field_formats_provider/field_formats.ts | 25 +++++++++++-------- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/plugins/data/common/field_formats/converters/date_server.ts b/src/plugins/data/common/field_formats/converters/date_server.ts index 0c214e424f163..34278ea9fe641 100644 --- a/src/plugins/data/common/field_formats/converters/date_server.ts +++ b/src/plugins/data/common/field_formats/converters/date_server.ts @@ -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 { @@ -32,7 +32,7 @@ export class DateFormat extends FieldFormat { private memoizedPattern: string = ''; private timeZone: string = ''; - constructor(params: Record, getConfig: Function) { + constructor(params: IFieldFormatMetaParams, getConfig: Function) { super(params, getConfig); this.memoizedConverter = memoize((val: any) => { diff --git a/src/plugins/data/common/field_formats/converters/url.ts b/src/plugins/data/common/field_formats/converters/url.ts index 3c88511a4c63e..21688dd8d1138 100644 --- a/src/plugins/data/common/field_formats/converters/url.ts +++ b/src/plugins/data/common/field_formats/converters/url.ts @@ -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; @@ -64,7 +64,7 @@ export class UrlFormat extends FieldFormat { ]; static urlTypes = URL_TYPES; - constructor(params: Record) { + constructor(params: IFieldFormatMetaParams) { super(params); this.compileTemplate = memoize(this.compileTemplate); } diff --git a/src/plugins/data/common/field_formats/field_format.ts b/src/plugins/data/common/field_formats/field_format.ts index 50f07846a3ceb..a0621b27f5bc0 100644 --- a/src/plugins/data/common/field_formats/field_format.ts +++ b/src/plugins/data/common/field_formats/field_format.ts @@ -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 @@ -90,7 +99,7 @@ export abstract class FieldFormat { protected readonly _params: any; protected getConfig: Function | undefined; - constructor(_params: Record = {}, getConfig?: Function) { + constructor(_params: IFieldFormatMetaParams = {}, getConfig?: Function) { this._params = _params; if (getConfig) { diff --git a/src/plugins/data/common/field_formats/index.ts b/src/plugins/data/common/field_formats/index.ts index b751b097b5ed2..b1e8744e26745 100644 --- a/src/plugins/data/common/field_formats/index.ts +++ b/src/plugins/data/common/field_formats/index.ts @@ -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'; diff --git a/src/plugins/data/public/field_formats_provider/field_formats.ts b/src/plugins/data/public/field_formats_provider/field_formats.ts index 38a29de1e2d58..d3d57d42028cd 100644 --- a/src/plugins/data/public/field_formats_provider/field_formats.ts +++ b/src/plugins/data/public/field_formats_provider/field_formats.ts @@ -27,6 +27,7 @@ import { IFieldFormatType, IFieldFormatId, FieldFormat, + IFieldFormatMetaParams, } from '../../common'; import { FieldType } from './types'; @@ -76,9 +77,9 @@ 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 => { + getType = (formatId: IFieldFormatId): IFieldFormatType | undefined => { const fieldFormat = this.fieldFormats.get(formatId); if (fieldFormat) { @@ -88,6 +89,8 @@ export class FieldFormatRegisty { return decoratedFieldFormat as IFieldFormatType; } } + + return undefined; }; /** @@ -97,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); @@ -113,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); @@ -241,11 +244,11 @@ export class FieldFormatRegisty { * * @private * @param {IFieldFormatType} fieldFormat - field format type - * @return {FieldFormat | void} + * @return {FieldFormat | undefined} */ private fieldFormatMetaParamsDecorator = ( fieldFormat: IFieldFormatType - ): IFieldFormatType | void => { + ): IFieldFormatType | undefined => { const getMetaParams = (customParams: Record) => this.buildMetaParams(customParams); if (fieldFormat) { @@ -258,6 +261,8 @@ export class FieldFormatRegisty { } }; } + + return undefined; }; /** @@ -267,7 +272,7 @@ export class FieldFormatRegisty { * @param {Record} custom params * @return {Record} */ - private buildMetaParams = (customParams: T = {}): T & {parsedUrl: ParsedUrl} => ({ + private buildMetaParams = (customParams: T): T => ({ parsedUrl: { origin: window.location.origin, pathname: window.location.pathname,