[7.x] Expose NP FieldFormats service to server side (#55419) (#56052)

* Expose NP FieldFormats service to server side (#55419)

* Expose NP FieldFormats service to server side

* fix CI

* fix PR comments

* fix PR comments

* fix CI

* getFieldFormatsRegistry -> getFieldFormatRegistry

* fix CI

* memoize - add resolve cache function

* fix Jest

* move IFieldFormatMetaParams to types.ts

* FieldFormatRegistry -> FieldFormatsRegistry

* update src/core/MIGRATION.md

* update public contract

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

# Conflicts:
#	x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js

* fix merge conflict
This commit is contained in:
Alexey Antonov 2020-01-28 02:01:47 +03:00 committed by GitHub
parent b450e87c8e
commit 470a50e5eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
70 changed files with 524 additions and 739 deletions

View file

@ -250,15 +250,15 @@ module.exports = {
{
target: [
'(src|x-pack)/plugins/**/*',
'!(src|x-pack)/plugins/*/server/**/*',
'!(src|x-pack)/plugins/**/server/**/*',
'src/legacy/core_plugins/**/*',
'!src/legacy/core_plugins/*/server/**/*',
'!src/legacy/core_plugins/*/index.{js,ts,tsx}',
'!src/legacy/core_plugins/**/server/**/*',
'!src/legacy/core_plugins/**/index.{js,ts,tsx}',
'x-pack/legacy/plugins/**/*',
'!x-pack/legacy/plugins/*/server/**/*',
'!x-pack/legacy/plugins/*/index.{js,ts,tsx}',
'!x-pack/legacy/plugins/**/server/**/*',
'!x-pack/legacy/plugins/**/index.{js,ts,tsx}',
'examples/**/*',
'!examples/**/server/**/*',

View file

@ -1231,8 +1231,8 @@ This table shows where these uiExports have moved to in the New Platform. In mos
| `docViews` | | |
| `embeddableActions` | | Should be an API on the embeddables plugin. |
| `embeddableFactories` | | Should be an API on the embeddables plugin. |
| `fieldFormatEditors` | | |
| `fieldFormats` | | |
| `fieldFormatEditors` | | |
| `fieldFormats` | [`plugins.data.fieldFormats`](./src/plugins/data/public/field_formats) | |
| `hacks` | n/a | Just run the code in your plugin's `start` method. |
| `home` | [`plugins.home.featureCatalogue.register`](./src/plugins/home/public/feature_catalogue) | Must add `home` as a dependency in your kibana.json. |
| `indexManagement` | | Should be an API on the indexManagement plugin. |

View file

@ -25,7 +25,6 @@ import { migrations } from './migrations';
import { importApi } from './server/routes/api/import';
import { exportApi } from './server/routes/api/export';
import { managementApi } from './server/routes/api/management';
import { registerFieldFormats } from './server/field_formats/register';
import * as systemApi from './server/lib/system_api';
import mappings from './mappings.json';
import { getUiSettingDefaults } from './ui_setting_defaults';
@ -331,7 +330,6 @@ export default function(kibana) {
importApi(server);
exportApi(server);
managementApi(server);
registerFieldFormats(server);
registerCspCollector(usageCollection, server);
server.expose('systemApi', systemApi);
server.injectUiAppVars('kibana', () => injectVars(server));

View file

@ -24,7 +24,7 @@ import { isColorDark } from '@elastic/eui';
import { getHeatmapColors, getFormat, Vis } from '../legacy_imports';
import { MetricVisValue } from './metric_vis_value';
import { FieldFormat, ContentType } from '../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../plugins/data/public';
import { Context } from '../metric_vis_fn';
import { KibanaDatatable } from '../../../../../plugins/expressions/public';
import { VisParams, MetricVisMetric } from '../types';
@ -100,9 +100,9 @@ export class MetricVisComponent extends Component<MetricVisComponentProps> {
}
private getFormattedValue = (
fieldFormatter: FieldFormat,
fieldFormatter: fieldFormats.FieldFormat,
value: any,
format: ContentType = 'text'
format: fieldFormats.ContentType = 'text'
) => {
if (isNaN(value)) return '-';
return fieldFormatter.convert(value, format);
@ -119,7 +119,7 @@ export class MetricVisComponent extends Component<MetricVisComponentProps> {
const metrics: MetricVisMetric[] = [];
let bucketColumnId: string;
let bucketFormatter: FieldFormat;
let bucketFormatter: fieldFormats.FieldFormat;
if (dimensions.bucket) {
bucketColumnId = table.columns[dimensions.bucket.accessor].id;

View file

@ -24,7 +24,7 @@ import { npStart } from 'ui/new_platform';
import getStubIndexPattern from 'fixtures/stubbed_logstash_index_pattern';
import { Vis } from '../../visualizations/public';
import { UrlFormat } from '../../../../plugins/data/public';
import { fieldFormats } from '../../../../plugins/data/public';
import {
setup as visualizationsSetup,
start as visualizationsStart,
@ -39,7 +39,7 @@ describe('metric_vis - createMetricVisTypeDefinition', () => {
beforeAll(() => {
visualizationsSetup.types.createReactVisualization(metricVisTypeDefinition);
(npStart.plugins.data.fieldFormats.getType as jest.Mock).mockImplementation(() => {
return UrlFormat;
return fieldFormats.UrlFormat;
});
});

View file

@ -26,7 +26,7 @@ import { calculateLabel } from '../../../../common/calculate_label';
import { isSortable } from './is_sortable';
import { EuiToolTip, EuiIcon } from '@elastic/eui';
import { replaceVars } from '../../lib/replace_vars';
import { FIELD_FORMAT_IDS } from '../../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../../plugins/data/public';
import { FormattedMessage } from '@kbn/i18n/react';
import { METRIC_TYPES } from '../../../../common/metric_types';
@ -49,8 +49,8 @@ export class TableVis extends Component {
constructor(props) {
super(props);
const fieldFormats = npStart.plugins.data.fieldFormats;
const DateFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE);
const fieldFormatsService = npStart.plugins.data.fieldFormats;
const DateFormat = fieldFormatsService.getType(fieldFormats.FIELD_FORMAT_IDS.DATE);
this.dateFormatter = new DateFormat({}, this.props.getConfig);
}

View file

@ -1,20 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export { fieldFormatsMixin } from './mixin/field_formats_mixin';

View file

@ -1,45 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { has } from 'lodash';
import { Legacy } from 'kibana';
import { FieldFormatsService } from './field_formats_service';
import { IFieldFormatType } from '../../../../plugins/data/public';
export function fieldFormatsMixin(kbnServer: any, server: Legacy.Server) {
const fieldFormatClasses: IFieldFormatType[] = [];
// for use outside of the request context, for special cases
server.decorate('server', 'fieldFormatServiceFactory', async function(uiSettings) {
const uiConfigs = await uiSettings.getAll();
const registeredUiSettings = uiSettings.getRegistered();
Object.keys(registeredUiSettings).forEach(key => {
if (has(uiConfigs, key) && registeredUiSettings[key].type === 'json') {
uiConfigs[key] = JSON.parse(uiConfigs[key]);
}
});
const getConfig = (key: string) => uiConfigs[key];
return new FieldFormatsService(fieldFormatClasses, getConfig);
});
server.decorate('server', 'registerFieldFormat', customFieldFormat => {
fieldFormatClasses.push(customFieldFormat);
});
}

View file

@ -1,56 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { FieldFormatsService } from './field_formats_service';
import { NumberFormat } from '../../../../plugins/data/public';
const getConfig = (key: string) => {
switch (key) {
case 'format:defaultTypeMap':
return {
number: { id: 'number', params: {} },
_default_: { id: 'string', params: {} },
};
case 'format:number:defaultPattern':
return '0,0.[000]';
}
};
describe('FieldFormatsService', () => {
let fieldFormatsService: FieldFormatsService;
beforeEach(() => {
const fieldFormatClasses = [NumberFormat];
fieldFormatsService = new FieldFormatsService(fieldFormatClasses, getConfig);
});
test('FieldFormats are accessible via getType method', () => {
const Type = fieldFormatsService.getType('number');
expect(Type.id).toBe('number');
});
test('getDefaultInstance returns default FieldFormat instance for fieldType', () => {
const instance = fieldFormatsService.getDefaultInstance('number');
expect(instance.type.id).toBe('number');
expect(instance.convert('0.33333')).toBe('0.333');
});
});

View file

@ -1,79 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { indexBy, Dictionary } from 'lodash';
import { FieldFormat, IFieldFormatType } from '../../../../plugins/data/common';
interface FieldFormatConfig {
id: string;
params?: Record<string, any>;
}
export class FieldFormatsService {
getConfig: any;
_fieldFormats: Dictionary<IFieldFormatType>;
constructor(fieldFormatClasses: IFieldFormatType[], getConfig: Function) {
this._fieldFormats = indexBy(fieldFormatClasses, 'id');
this.getConfig = getConfig;
}
/**
* Get the id of the default type for this field type
* using the format:defaultTypeMap config map
*
* @param {String} fieldType - the field type
* @return {FieldFormatConfig}
*/
getDefaultConfig(fieldType: string): FieldFormatConfig {
const defaultMap = this.getConfig('format:defaultTypeMap');
return defaultMap[fieldType] || defaultMap._default_;
}
/**
* Get the default fieldFormat instance for a field type.
*
* @param {String} fieldType
* @return {FieldFormat}
*/
getDefaultInstance(fieldType: string): FieldFormat {
return this.getInstance(this.getDefaultConfig(fieldType));
}
/**
* Get the fieldFormat instance for a field format configuration.
*
* @param {FieldFormatConfig} field format config
* @return {FieldFormat}
*/
getInstance(conf: FieldFormatConfig): FieldFormat {
// @ts-ignore
return new this._fieldFormats[conf.id](conf.params, this.getConfig);
}
/**
* Get a FieldFormat type (class) by it's id.
*
* @param {String} fieldFormatId - the FieldFormat id
* @return {FieldFormat}
*/
getType(fieldFormatId: string): any {
return this._fieldFormats[fieldFormatId];
}
}

View file

@ -34,9 +34,9 @@ import { AggConfigs } from './agg_configs';
import { Schema } from '../vis/editors/default/schemas';
import {
ISearchSource,
ContentType,
KBN_FIELD_TYPES,
FetchOptions,
fieldFormats,
KBN_FIELD_TYPES,
} from '../../../../plugins/data/public';
export interface AggConfigOptions {
@ -375,7 +375,7 @@ export class AggConfig {
return this.aggConfigs.timeRange;
}
fieldFormatter(contentType?: ContentType, defaultFormat?: any) {
fieldFormatter(contentType?: fieldFormats.ContentType, defaultFormat?: any) {
const format = this.type && this.type.getFormat(this);
if (format) {
@ -385,12 +385,12 @@ export class AggConfig {
return this.fieldOwnFormatter(contentType, defaultFormat);
}
fieldOwnFormatter(contentType?: ContentType, defaultFormat?: any) {
const fieldFormats = npStart.plugins.data.fieldFormats;
fieldOwnFormatter(contentType?: fieldFormats.ContentType, defaultFormat?: any) {
const fieldFormatsService = npStart.plugins.data.fieldFormats;
const field = this.getField();
let format = field && field.format;
if (!format) format = defaultFormat;
if (!format) format = fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING);
if (!format) format = fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.STRING);
return format.getConverterFor(contentType);
}

View file

@ -27,7 +27,7 @@ import { AggConfigs } from './agg_configs';
import { Adapters } from '../inspector';
import { BaseParamType } from './param_types/base';
import { AggParamType } from '../agg_types/param_types/agg';
import { KBN_FIELD_TYPES, FieldFormat, ISearchSource } from '../../../../plugins/data/public';
import { KBN_FIELD_TYPES, fieldFormats, ISearchSource } from '../../../../plugins/data/public';
export interface AggTypeConfig<
TAggConfig extends AggConfig = AggConfig,
@ -54,16 +54,16 @@ export interface AggTypeConfig<
inspectorAdapters: Adapters,
abortSignal?: AbortSignal
) => Promise<any>;
getFormat?: (agg: TAggConfig) => FieldFormat;
getFormat?: (agg: TAggConfig) => fieldFormats.FieldFormat;
getValue?: (agg: TAggConfig, bucket: any) => any;
getKey?: (bucket: any, key: any, agg: TAggConfig) => any;
}
const getFormat = (agg: AggConfig) => {
const field = agg.getField();
const fieldFormats = npStart.plugins.data.fieldFormats;
const fieldFormatsService = npStart.plugins.data.fieldFormats;
return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING);
return field ? field.format : fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.STRING);
};
export class AggType<
@ -191,7 +191,7 @@ export class AggType<
* @param {agg} agg - the agg to pick a format for
* @return {FieldFormat}
*/
getFormat: (agg: TAggConfig) => FieldFormat;
getFormat: (agg: TAggConfig) => fieldFormats.FieldFormat;
getValue: (agg: TAggConfig, bucket: any) => any;

View file

@ -19,7 +19,7 @@
import moment from 'moment';
import { createFilterDateRange } from './date_range';
import { DateFormat } from '../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../plugins/data/public';
import { AggConfigs } from '../../agg_configs';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
@ -28,10 +28,11 @@ jest.mock('ui/new_platform');
describe('AggConfig Filters', () => {
describe('Date range', () => {
const getConfig = (() => {}) as fieldFormats.GetConfigFn;
const getAggConfigs = () => {
const field = {
name: '@timestamp',
format: new DateFormat({}, () => {}),
format: new fieldFormats.DateFormat({}, getConfig),
};
const indexPattern = {

View file

@ -20,16 +20,17 @@ import { createFilterHistogram } from './histogram';
import { AggConfigs } from '../../agg_configs';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
import { BytesFormat } from '../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../plugins/data/public';
jest.mock('ui/new_platform');
describe('AggConfig Filters', () => {
describe('histogram', () => {
const getConfig = (() => {}) as fieldFormats.GetConfigFn;
const getAggConfigs = () => {
const field = {
name: 'bytes',
format: new BytesFormat({}, () => {}),
format: new fieldFormats.BytesFormat({}, getConfig),
};
const indexPattern = {

View file

@ -19,7 +19,7 @@
import { createFilterIpRange } from './ip_range';
import { AggConfigs } from '../../agg_configs';
import { IpFormat } from '../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../plugins/data/public';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
@ -30,7 +30,7 @@ describe('AggConfig Filters', () => {
const getAggConfigs = (aggs: Array<Record<string, any>>) => {
const field = {
name: 'ip',
format: IpFormat,
format: fieldFormats.IpFormat,
};
const indexPattern = {

View file

@ -18,7 +18,7 @@
*/
import { createFilterRange } from './range';
import { BytesFormat } from '../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../plugins/data/public';
import { AggConfigs } from '../../agg_configs';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
@ -27,10 +27,11 @@ jest.mock('ui/new_platform');
describe('AggConfig Filters', () => {
describe('range', () => {
const getConfig = (() => {}) as fieldFormats.GetConfigFn;
const getAggConfigs = () => {
const field = {
name: 'bytes',
format: new BytesFormat({}, () => {}),
format: new fieldFormats.BytesFormat({}, getConfig),
};
const indexPattern = {

View file

@ -25,11 +25,7 @@ import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
import { createFilterDateRange } from './create_filter/date_range';
import { DateRangesParamEditor } from '../../vis/editors/default/controls/date_ranges';
import {
KBN_FIELD_TYPES,
TEXT_CONTEXT_TYPE,
FieldFormat,
} from '../../../../../plugins/data/public';
import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../plugins/data/public';
const dateRangeTitle = i18n.translate('common.ui.aggTypes.buckets.dateRangeTitle', {
defaultMessage: 'Date Range',
@ -48,13 +44,13 @@ export const dateRangeBucketAgg = new BucketAggType({
return { from, to };
},
getFormat(agg) {
const fieldFormats = npStart.plugins.data.fieldFormats;
const fieldFormatsService = npStart.plugins.data.fieldFormats;
const formatter = agg.fieldOwnFormatter(
TEXT_CONTEXT_TYPE,
fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE)
fieldFormats.TEXT_CONTEXT_TYPE,
fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.DATE)
);
const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) {
const DateRangeFormat = fieldFormats.FieldFormat.from(function(range: DateRangeKey) {
return convertDateRangeToString(range, formatter);
});
return new DateRangeFormat();

View file

@ -27,11 +27,7 @@ import { BUCKET_TYPES } from './bucket_agg_types';
// @ts-ignore
import { createFilterIpRange } from './create_filter/ip_range';
import {
KBN_FIELD_TYPES,
TEXT_CONTEXT_TYPE,
FieldFormat,
} from '../../../../../plugins/data/public';
import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../plugins/data/public';
const ipRangeTitle = i18n.translate('common.ui.aggTypes.buckets.ipRangeTitle', {
defaultMessage: 'IPv4 Range',
@ -52,12 +48,12 @@ export const ipRangeBucketAgg = new BucketAggType({
return { type: 'range', from: bucket.from, to: bucket.to };
},
getFormat(agg) {
const fieldFormats = npStart.plugins.data.fieldFormats;
const fieldFormatsService = npStart.plugins.data.fieldFormats;
const formatter = agg.fieldOwnFormatter(
TEXT_CONTEXT_TYPE,
fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.IP)
fieldFormats.TEXT_CONTEXT_TYPE,
fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.IP)
);
const IpRangeFormat = FieldFormat.from(function(range: IpRangeKey) {
const IpRangeFormat = fieldFormats.FieldFormat.from(function(range: IpRangeKey) {
return convertIPRangeToString(range, formatter);
});
return new IpRangeFormat();

View file

@ -19,7 +19,7 @@
import { AggConfigs } from '../agg_configs';
import { BUCKET_TYPES } from './bucket_agg_types';
import { NumberFormat } from '../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../plugins/data/public';
jest.mock('ui/new_platform');
@ -44,14 +44,15 @@ const buckets = [
];
describe('Range Agg', () => {
const getConfig = (() => {}) as fieldFormats.GetConfigFn;
const getAggConfigs = () => {
const field = {
name: 'bytes',
format: new NumberFormat(
format: new fieldFormats.NumberFormat(
{
pattern: '0,0.[000] b',
},
() => {}
getConfig
),
};

View file

@ -19,7 +19,7 @@
import { i18n } from '@kbn/i18n';
import { BucketAggType } from './_bucket_agg_type';
import { FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public';
import { fieldFormats, KBN_FIELD_TYPES } from '../../../../../plugins/data/public';
import { RangeKey } from './range_key';
import { RangesEditor } from './range_editor';
@ -68,7 +68,7 @@ export const rangeBucketAgg = new BucketAggType({
let aggFormat = formats.get(agg);
if (aggFormat) return aggFormat;
const RangeFormat = FieldFormat.from((range: any) => {
const RangeFormat = fieldFormats.FieldFormat.from((range: any) => {
const format = agg.fieldOwnFormatter();
const gte = '\u2265';
const lt = '\u003c';

View file

@ -38,12 +38,7 @@ import { OtherBucketParamEditor } from '../../vis/editors/default/controls/other
import { AggConfigs } from '../agg_configs';
import { Adapters } from '../../../../../plugins/inspector/public';
import {
ContentType,
ISearchSource,
FieldFormat,
KBN_FIELD_TYPES,
} from '../../../../../plugins/data/public';
import { ISearchSource, fieldFormats, KBN_FIELD_TYPES } from '../../../../../plugins/data/public';
// @ts-ignore
import { Schemas } from '../../vis/editors/default/schemas';
@ -77,9 +72,9 @@ export const termsBucketAgg = new BucketAggType({
const params = agg.params;
return agg.getFieldDisplayName() + ': ' + params.order.text;
},
getFormat(bucket): FieldFormat {
getFormat(bucket): fieldFormats.FieldFormat {
return {
getConverterFor: (type: ContentType) => {
getConverterFor: (type: fieldFormats.ContentType) => {
return (val: any) => {
if (val === '__other__') {
return bucket.params.otherBucketLabel;
@ -91,7 +86,7 @@ export const termsBucketAgg = new BucketAggType({
return bucket.params.field.format.convert(val, type);
};
},
} as FieldFormat;
} as fieldFormats.FieldFormat;
},
createFilter: createFilterTerms,
postFlightRequest: async (

View file

@ -37,9 +37,9 @@ export const cardinalityMetricAgg = new MetricAggType({
});
},
getFormat() {
const fieldFormats = npStart.plugins.data.fieldFormats;
const fieldFormatsService = npStart.plugins.data.fieldFormats;
return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
},
params: [
{

View file

@ -35,9 +35,9 @@ export const countMetricAgg = new MetricAggType({
});
},
getFormat() {
const fieldFormats = npStart.plugins.data.fieldFormats;
const fieldFormatsService = npStart.plugins.data.fieldFormats;
return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
},
getValue(agg, bucket) {
return bucket.doc_count;

View file

@ -74,9 +74,11 @@ export class MetricAggType<TMetricAggConfig extends AggConfig = IMetricAggConfig
this.getFormat =
config.getFormat ||
(agg => {
const registeredFormats = npStart.plugins.data.fieldFormats;
const fieldFormatsService = npStart.plugins.data.fieldFormats;
const field = agg.getField();
return field ? field.format : registeredFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
return field
? field.format
: fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
});
this.subtype =

View file

@ -25,7 +25,7 @@ import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_respons
import { getPercentileValue } from './percentiles_get_value';
import { METRIC_TYPES } from './metric_agg_types';
import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../../plugins/data/public';
import { fieldFormats, KBN_FIELD_TYPES } from '../../../../../plugins/data/public';
// required by the values editor
@ -35,10 +35,10 @@ const getFieldFormats = () => npStart.plugins.data.fieldFormats;
const valueProps = {
makeLabel(this: IPercentileRanksAggConfig) {
const fieldFormats = getFieldFormats();
const fieldFormatsService = getFieldFormats();
const field = this.getField();
const format =
(field && field.format) || fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
(field && field.format) || fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
const customLabel = this.getParam('customLabel');
const label = customLabel || this.getFieldDisplayName();
@ -84,10 +84,10 @@ export const percentileRanksMetricAgg = new MetricAggType<IPercentileRanksAggCon
return values.map((value: any) => new ValueAggConfig(value));
},
getFormat() {
const fieldFormats = getFieldFormats();
const fieldFormatsService = getFieldFormats();
return (
fieldFormats.getInstance(FIELD_FORMAT_IDS.PERCENT) ||
fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER)
fieldFormatsService.getInstance(fieldFormats.FIELD_FORMAT_IDS.PERCENT) ||
fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER)
);
},
getValue(agg, bucket) {

View file

@ -23,7 +23,7 @@ import { EuiBasicTable, EuiButton, EuiColorPicker, EuiFieldText, EuiSpacer } fro
import { DefaultFormatEditor } from '../default';
import { DEFAULT_CONVERTER_COLOR } from '../../../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../../../plugins/data/public';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@ -50,7 +50,7 @@ export class ColorFormatEditor extends DefaultFormatEditor {
addColor = () => {
const colors = [...this.props.formatParams.colors];
this.onChange({
colors: [...colors, { ...DEFAULT_CONVERTER_COLOR }],
colors: [...colors, { ...fieldFormats.DEFAULT_CONVERTER_COLOR }],
});
};

View file

@ -21,14 +21,14 @@ import React from 'react';
import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers';
import { ColorFormatEditor } from './color';
import { DEFAULT_CONVERTER_COLOR } from '../../../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../../../plugins/data/public';
const fieldType = 'string';
const format = {
getConverterFor: jest.fn(),
};
const formatParams = {
colors: [{ ...DEFAULT_CONVERTER_COLOR }],
colors: [{ ...fieldFormats.DEFAULT_CONVERTER_COLOR }],
};
const onChange = jest.fn();
const onError = jest.fn();

View file

@ -18,7 +18,7 @@
*/
import { getDefaultFormat } from '../get_default_format';
import { NumberFormat } from '../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../plugins/data/public';
const getConfig = () => {
return '0,0.[000]';
@ -26,12 +26,12 @@ const getConfig = () => {
describe('getDefaultFormat', () => {
it('should create default format', () => {
const DefaultFormat = getDefaultFormat(NumberFormat);
const DefaultFormat = getDefaultFormat(fieldFormats.NumberFormat);
const defaultFormatObject = new DefaultFormat(null, getConfig);
const formatObject = new NumberFormat(null, getConfig);
const formatObject = new fieldFormats.NumberFormat(null, getConfig);
expect(DefaultFormat.id).toEqual('');
expect(DefaultFormat.resolvedTitle).toEqual(NumberFormat.title);
expect(DefaultFormat.resolvedTitle).toEqual(fieldFormats.NumberFormat.title);
expect(DefaultFormat.title).toEqual('- Default -');
expect(JSON.stringify(defaultFormatObject.params())).toEqual(
JSON.stringify(formatObject.params())

View file

@ -25,7 +25,7 @@ import {
convertDurationToNormalizedEsInterval,
convertIntervalToEsInterval,
} from './calc_es_interval';
import { FIELD_FORMAT_IDS, parseInterval } from '../../../../plugins/data/public';
import { fieldFormats, parseInterval } from '../../../../plugins/data/public';
const getConfig = (...args) => npStart.core.uiSettings.get(...args);
@ -308,8 +308,8 @@ TimeBuckets.prototype.getScaledDateFormat = function() {
};
TimeBuckets.prototype.getScaledDateFormatter = function() {
const fieldFormats = npStart.plugins.data.fieldFormats;
const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE);
const fieldFormatsService = npStart.plugins.data.fieldFormats;
const DateFieldFormat = fieldFormatsService.getType(fieldFormats.FIELD_FORMAT_IDS.DATE);
return new DateFieldFormat(
{

View file

@ -22,8 +22,7 @@ import { identity } from 'lodash';
import { AggConfig, Vis } from 'ui/vis';
import { npStart } from 'ui/new_platform';
import { SerializedFieldFormat } from 'src/plugins/expressions/public';
import { IFieldFormatId, FieldFormat, ContentType } from '../../../../../../plugins/data/public';
import { fieldFormats } from '../../../../../../plugins/data/public';
import { tabifyGetColumns } from '../../../agg_response/tabify/_get_columns';
import { DateRangeKey, convertDateRangeToString } from '../../../agg_types/buckets/date_range';
@ -43,13 +42,16 @@ function isTermsFieldFormat(
const getConfig = (key: string, defaultOverride?: any): any =>
npStart.core.uiSettings.get(key, defaultOverride);
const DefaultFieldFormat = FieldFormat.from(identity);
const DefaultFieldFormat = fieldFormats.FieldFormat.from(identity);
const getFieldFormat = (id?: IFieldFormatId, params: object = {}): FieldFormat => {
const fieldFormats = npStart.plugins.data.fieldFormats;
const getFieldFormat = (
id?: fieldFormats.IFieldFormatId,
params: object = {}
): fieldFormats.FieldFormat => {
const fieldFormatsService = npStart.plugins.data.fieldFormats;
if (id) {
const Format = fieldFormats.getType(id);
const Format = fieldFormatsService.getType(id);
if (Format) {
return new Format(params, getConfig);
@ -91,7 +93,7 @@ export const createFormat = (agg: AggConfig): SerializedFieldFormat => {
return formats[agg.type.name] ? formats[agg.type.name]() : format;
};
export type FormatFactory = (mapping?: SerializedFieldFormat) => FieldFormat;
export type FormatFactory = (mapping?: SerializedFieldFormat) => fieldFormats.FieldFormat;
export const getFormat: FormatFactory = mapping => {
if (!mapping) {
@ -99,7 +101,7 @@ export const getFormat: FormatFactory = mapping => {
}
const { id } = mapping;
if (id === 'range') {
const RangeFormat = FieldFormat.from((range: any) => {
const RangeFormat = fieldFormats.FieldFormat.from((range: any) => {
const format = getFieldFormat(id, mapping.params);
const gte = '\u2265';
const lt = '\u003c';
@ -116,21 +118,21 @@ export const getFormat: FormatFactory = mapping => {
return new RangeFormat();
} else if (id === 'date_range') {
const nestedFormatter = mapping.params as SerializedFieldFormat;
const DateRangeFormat = FieldFormat.from((range: DateRangeKey) => {
const DateRangeFormat = fieldFormats.FieldFormat.from((range: DateRangeKey) => {
const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params);
return convertDateRangeToString(range, format.convert.bind(format));
});
return new DateRangeFormat();
} else if (id === 'ip_range') {
const nestedFormatter = mapping.params as SerializedFieldFormat;
const IpRangeFormat = FieldFormat.from((range: IpRangeKey) => {
const IpRangeFormat = fieldFormats.FieldFormat.from((range: IpRangeKey) => {
const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params);
return convertIPRangeToString(range, format.convert.bind(format));
});
return new IpRangeFormat();
} else if (isTermsFieldFormat(mapping) && mapping.params) {
const { params } = mapping;
const convert = (val: string, type: ContentType) => {
const convert = (val: string, type: fieldFormats.ContentType) => {
const format = getFieldFormat(params.id, mapping.params);
if (val === '__other__') {
@ -145,8 +147,8 @@ export const getFormat: FormatFactory = mapping => {
return {
convert,
getConverterFor: (type: ContentType) => (val: string) => convert(val, type),
} as FieldFormat;
getConverterFor: (type: fieldFormats.ContentType) => (val: string) => convert(val, type),
} as fieldFormats.FieldFormat;
} else {
return getFieldFormat(id, mapping.params);
}
@ -159,5 +161,3 @@ export const getTableAggs = (vis: Vis): AggConfig[] => {
const columns = tabifyGetColumns(vis.aggs.getResponseAggs(), !vis.isHierarchical());
return columns.map(c => c.aggConfig);
};
export { FieldFormat };

View file

@ -17,7 +17,6 @@
* under the License.
*/
import { fieldFormatsMixin } from './field_formats';
import { uiAppsMixin } from './ui_apps';
import { uiBundlesMixin } from './ui_bundles';
import { uiRenderMixin } from './ui_render';
@ -27,6 +26,5 @@ export async function uiMixin(kbnServer) {
await kbnServer.mixin(uiAppsMixin);
await kbnServer.mixin(uiBundlesMixin);
await kbnServer.mixin(uiSettingsMixin);
await kbnServer.mixin(fieldFormatsMixin);
await kbnServer.mixin(uiRenderMixin);
}

View file

@ -17,38 +17,40 @@
* under the License.
*/
import { IFieldFormatType } from '../types';
import {
UrlFormat,
StringFormat,
NumberFormat,
BytesFormat,
TruncateFormat,
RelativeDateFormat,
PercentFormat,
IpFormat,
DurationFormat,
DateNanosFormat,
DateFormat,
ColorFormat,
BoolFormat,
BytesFormat,
ColorFormat,
DateFormat,
DateNanosFormat,
DurationFormat,
IpFormat,
NumberFormat,
PercentFormat,
RelativeDateFormat,
SourceFormat,
StaticLookupFormat,
} from '../../../../../plugins/data/server';
StringFormat,
TruncateFormat,
UrlFormat,
} from '../converters';
export function registerFieldFormats(server) {
server.registerFieldFormat(UrlFormat);
server.registerFieldFormat(BytesFormat);
server.registerFieldFormat(DateFormat);
server.registerFieldFormat(DateNanosFormat);
server.registerFieldFormat(RelativeDateFormat);
server.registerFieldFormat(DurationFormat);
server.registerFieldFormat(IpFormat);
server.registerFieldFormat(NumberFormat);
server.registerFieldFormat(PercentFormat);
server.registerFieldFormat(StringFormat);
server.registerFieldFormat(SourceFormat);
server.registerFieldFormat(ColorFormat);
server.registerFieldFormat(TruncateFormat);
server.registerFieldFormat(BoolFormat);
server.registerFieldFormat(StaticLookupFormat);
}
export const baseFormatters: IFieldFormatType[] = [
BoolFormat,
BytesFormat,
ColorFormat,
DateFormat,
DateNanosFormat,
DurationFormat,
IpFormat,
NumberFormat,
PercentFormat,
RelativeDateFormat,
SourceFormat,
StaticLookupFormat,
StringFormat,
TruncateFormat,
UrlFormat,
];

View file

@ -22,7 +22,7 @@ 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';
import { DEFAULT_CONVERTER_COLOR } from '../constants/color_default';
const convertTemplate = template('<span style="<%- style %>"><%- val %></span>');

View file

@ -17,8 +17,8 @@
* under the License.
*/
import { FieldFormat, IFieldFormatType } from '../field_format';
import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types';
import { FieldFormat } from '../field_format';
import { TextContextTypeConvert, FIELD_FORMAT_IDS, IFieldFormatType } from '../types';
export const createCustomFieldFormat = (convert: TextContextTypeConvert): IFieldFormatType =>
class CustomFieldFormat extends FieldFormat {

View file

@ -20,8 +20,13 @@
import { memoize, noop } from 'lodash';
import moment from 'moment-timezone';
import { KBN_FIELD_TYPES } from '../../kbn_field_types/types';
import { FieldFormat, IFieldFormatMetaParams } from '../field_format';
import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types';
import { FieldFormat } from '../field_format';
import {
TextContextTypeConvert,
FIELD_FORMAT_IDS,
GetConfigFn,
IFieldFormatMetaParams,
} from '../types';
export class DateFormat extends FieldFormat {
static id = FIELD_FORMAT_IDS.DATE;
@ -32,7 +37,7 @@ export class DateFormat extends FieldFormat {
private memoizedPattern: string = '';
private timeZone: string = '';
constructor(params: IFieldFormatMetaParams, getConfig: Function) {
constructor(params: IFieldFormatMetaParams, getConfig: GetConfigFn) {
super(params, getConfig);
this.memoizedConverter = memoize((val: any) => {

View file

@ -18,7 +18,7 @@
*/
import { i18n } from '@kbn/i18n';
import { asPrettyString } from '../index';
import { asPrettyString } from '../utils';
import { KBN_FIELD_TYPES } from '../../kbn_field_types/types';
import { FieldFormat } from '../field_format';
import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types';

View file

@ -21,8 +21,13 @@ 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, IFieldFormatMetaParams } from '../field_format';
import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types';
import { FieldFormat } from '../field_format';
import {
TextContextTypeConvert,
HtmlContextTypeConvert,
IFieldFormatMetaParams,
FIELD_FORMAT_IDS,
} from '../types';
const templateMatchRE = /{{([\s\S]+?)}}/g;
const whitelistUrlSchemes = ['http://', 'https://'];

View file

@ -20,12 +20,14 @@
import { transform, size, cloneDeep, get, defaults } from 'lodash';
import { createCustomFieldFormat } from './converters/custom';
import {
GetConfigFn,
ContentType,
FIELD_FORMAT_IDS,
IFieldFormatType,
FieldFormatConvert,
FieldFormatConvertFunction,
HtmlContextTypeOptions,
TextContextTypeOptions,
IFieldFormatMetaParams,
} from './types';
import {
htmlContentTypeSetup,
@ -37,15 +39,6 @@ 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
@ -97,9 +90,9 @@ export abstract class FieldFormat {
public type: any = this.constructor;
protected readonly _params: any;
protected getConfig: Function | undefined;
protected getConfig: GetConfigFn | undefined;
constructor(_params: IFieldFormatMetaParams = {}, getConfig?: Function) {
constructor(_params: IFieldFormatMetaParams = {}, getConfig?: GetConfigFn) {
this._params = _params;
if (getConfig) {
@ -226,13 +219,3 @@ export abstract class FieldFormat {
return Boolean(fieldFormat && fieldFormat.convert);
}
}
export type IFieldFormat = PublicMethodsOf<FieldFormat>;
/**
* @string id type is needed for creating custom converters.
*/
export type IFieldFormatId = FIELD_FORMAT_IDS | string;
export type IFieldFormatType = (new (params?: any, getConfig?: Function) => FieldFormat) & {
id: IFieldFormatId;
fieldType: string | string[];
};

View file

@ -16,72 +16,67 @@
* specific language governing permissions and limitations
* under the License.
*/
import { CoreSetup, IUiSettingsClient } from 'kibana/public';
import { FieldFormatRegisty } from './field_formats';
import {
BoolFormat,
IFieldFormatType,
PercentFormat,
StringFormat,
} from '../../common/field_formats';
import { coreMock } from '../../../../core/public/mocks';
import { FieldFormatsRegistry } from './field_formats_registry';
import { BoolFormat, PercentFormat, StringFormat } from './converters';
import { GetConfigFn, IFieldFormatType } from './types';
import { KBN_FIELD_TYPES } from '../../common';
const getValueOfPrivateField = (instance: any, field: string) => instance[field];
const getUiSettingsMock = (data: any): IUiSettingsClient['get'] => () => data;
describe('FieldFormatRegisty', () => {
let mockCoreSetup: CoreSetup;
let fieldFormatRegisty: FieldFormatRegisty;
describe('FieldFormatsRegistry', () => {
let fieldFormatsRegistry: FieldFormatsRegistry;
let defaultMap = {};
const getConfig = (() => defaultMap) as GetConfigFn;
beforeEach(() => {
mockCoreSetup = coreMock.createSetup();
fieldFormatRegisty = new FieldFormatRegisty();
fieldFormatsRegistry = new FieldFormatsRegistry();
fieldFormatsRegistry.init(
getConfig,
{
parsedUrl: {
origin: '',
pathname: '',
basePath: '',
},
},
[]
);
});
test('should allows to create an instance of "FieldFormatRegisty"', () => {
expect(fieldFormatRegisty).toBeDefined();
expect(getValueOfPrivateField(fieldFormatRegisty, 'fieldFormats')).toBeDefined();
expect(getValueOfPrivateField(fieldFormatRegisty, 'defaultMap')).toEqual({});
test('should allows to create an instance of "FieldFormatsRegistry"', () => {
expect(fieldFormatsRegistry).toBeDefined();
expect(getValueOfPrivateField(fieldFormatsRegistry, 'fieldFormats')).toBeDefined();
expect(getValueOfPrivateField(fieldFormatsRegistry, 'defaultMap')).toEqual({});
});
describe('init', () => {
test('should provide an public "init" method', () => {
expect(fieldFormatRegisty.init).toBeDefined();
expect(typeof fieldFormatRegisty.init).toBe('function');
});
test('should set basePath value from "init" method', () => {
fieldFormatRegisty.init(mockCoreSetup);
expect(getValueOfPrivateField(fieldFormatRegisty, 'basePath')).toBe(
mockCoreSetup.http.basePath.get()
);
expect(fieldFormatsRegistry.init).toBeDefined();
expect(typeof fieldFormatsRegistry.init).toBe('function');
});
test('should populate the "defaultMap" object', () => {
const defaultMap = {
defaultMap = {
number: { id: 'number', params: {} },
};
mockCoreSetup.uiSettings.get = getUiSettingsMock(defaultMap);
fieldFormatRegisty.init(mockCoreSetup);
expect(getValueOfPrivateField(fieldFormatRegisty, 'defaultMap')).toEqual(defaultMap);
fieldFormatsRegistry.init(getConfig, {}, []);
expect(getValueOfPrivateField(fieldFormatsRegistry, 'defaultMap')).toEqual(defaultMap);
});
});
describe('register', () => {
test('should provide an public "register" method', () => {
expect(fieldFormatRegisty.register).toBeDefined();
expect(typeof fieldFormatRegisty.register).toBe('function');
expect(fieldFormatsRegistry.register).toBeDefined();
expect(typeof fieldFormatsRegistry.register).toBe('function');
});
test('should register field formats', () => {
fieldFormatRegisty.register([StringFormat, BoolFormat]);
fieldFormatsRegistry.register([StringFormat, BoolFormat]);
const registeredFieldFormatters: Map<string, IFieldFormatType> = getValueOfPrivateField(
fieldFormatRegisty,
fieldFormatsRegistry,
'fieldFormats'
);
@ -95,28 +90,28 @@ describe('FieldFormatRegisty', () => {
describe('getType', () => {
test('should provide an public "getType" method', () => {
expect(fieldFormatRegisty.getType).toBeDefined();
expect(typeof fieldFormatRegisty.getType).toBe('function');
expect(fieldFormatsRegistry.getType).toBeDefined();
expect(typeof fieldFormatsRegistry.getType).toBe('function');
});
test('should return the registered type of the field format by identifier', () => {
fieldFormatRegisty.register([StringFormat]);
fieldFormatsRegistry.register([StringFormat]);
expect(fieldFormatRegisty.getType(StringFormat.id)).toBeDefined();
expect(fieldFormatsRegistry.getType(StringFormat.id)).toBeDefined();
});
test('should return void if the field format type has not been registered', () => {
fieldFormatRegisty.register([BoolFormat]);
fieldFormatsRegistry.register([BoolFormat]);
expect(fieldFormatRegisty.getType(StringFormat.id)).toBeUndefined();
expect(fieldFormatsRegistry.getType(StringFormat.id)).toBeUndefined();
});
});
describe('fieldFormatMetaParamsDecorator', () => {
test('should set meta params for all instances of FieldFormats', () => {
fieldFormatRegisty.register([StringFormat]);
fieldFormatsRegistry.register([StringFormat]);
const DecoratedStingFormat = fieldFormatRegisty.getType(StringFormat.id);
const DecoratedStingFormat = fieldFormatsRegistry.getType(StringFormat.id);
expect(DecoratedStingFormat).toBeDefined();
@ -135,9 +130,9 @@ describe('FieldFormatRegisty', () => {
});
test('should decorate static fields', () => {
fieldFormatRegisty.register([BoolFormat]);
fieldFormatsRegistry.register([BoolFormat]);
const DecoratedBoolFormat = fieldFormatRegisty.getType(BoolFormat.id);
const DecoratedBoolFormat = fieldFormatsRegistry.getType(BoolFormat.id);
expect(DecoratedBoolFormat).toBeDefined();
@ -150,14 +145,14 @@ describe('FieldFormatRegisty', () => {
describe('getByFieldType', () => {
test('should provide an public "getByFieldType" method', () => {
expect(fieldFormatRegisty.getByFieldType).toBeDefined();
expect(typeof fieldFormatRegisty.getByFieldType).toBe('function');
expect(fieldFormatsRegistry.getByFieldType).toBeDefined();
expect(typeof fieldFormatsRegistry.getByFieldType).toBe('function');
});
test('should decorate returns types', () => {
fieldFormatRegisty.register([StringFormat, BoolFormat]);
fieldFormatsRegistry.register([StringFormat, BoolFormat]);
const [DecoratedStringFormat] = fieldFormatRegisty.getByFieldType(KBN_FIELD_TYPES.STRING);
const [DecoratedStringFormat] = fieldFormatsRegistry.getByFieldType(KBN_FIELD_TYPES.STRING);
expect(DecoratedStringFormat).toBeDefined();

View file

@ -19,42 +19,36 @@
// eslint-disable-next-line max-classes-per-file
import { forOwn, isFunction, memoize } from 'lodash';
import { IUiSettingsClient, CoreSetup } from 'kibana/public';
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../common';
import {
ES_FIELD_TYPES,
KBN_FIELD_TYPES,
GetConfigFn,
IFieldFormatConfig,
FIELD_FORMAT_IDS,
IFieldFormatType,
IFieldFormatId,
FieldFormat,
IFieldFormatMetaParams,
} from '../../common';
import { FieldType } from './types';
} from './types';
import { baseFormatters } from './constants/base_formatters';
import { FieldFormat } from './field_format';
export class FieldFormatRegisty {
private fieldFormats: Map<IFieldFormatId, IFieldFormatType>;
private uiSettings!: IUiSettingsClient;
private defaultMap: Record<string, FieldType>;
private basePath?: string;
export class FieldFormatsRegistry {
protected fieldFormats: Map<IFieldFormatId, IFieldFormatType> = new Map();
protected defaultMap: Record<string, IFieldFormatConfig> = {};
protected metaParamsOptions: Record<string, any> = {};
protected getConfig?: GetConfigFn;
constructor() {
this.fieldFormats = new Map();
this.defaultMap = {};
}
getConfig = (key: string, override?: any) => this.uiSettings.get(key, override);
init({ uiSettings, http }: CoreSetup) {
this.uiSettings = uiSettings;
this.basePath = http.basePath.get();
this.parseDefaultTypeMap(this.uiSettings.get('format:defaultTypeMap'));
this.uiSettings.getUpdate$().subscribe(({ key, newValue }) => {
if (key === 'format:defaultTypeMap') {
this.parseDefaultTypeMap(newValue);
}
});
init(
getConfig: GetConfigFn,
metaParamsOptions: Record<string, any> = {},
defaultFieldConverters: IFieldFormatType[] = baseFormatters
) {
const defaultTypeMap = getConfig('format:defaultTypeMap');
this.register(defaultFieldConverters);
this.parseDefaultTypeMap(defaultTypeMap);
this.getConfig = getConfig;
this.metaParamsOptions = metaParamsOptions;
}
/**
@ -65,7 +59,10 @@ export class FieldFormatRegisty {
* @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types
* @return {FieldType}
*/
getDefaultConfig = (fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldType => {
getDefaultConfig = (
fieldType: KBN_FIELD_TYPES,
esTypes?: ES_FIELD_TYPES[]
): IFieldFormatConfig => {
const type = this.getDefaultTypeName(fieldType, esTypes);
return (
@ -151,14 +148,19 @@ export class FieldFormatRegisty {
*/
getInstance = memoize(
(formatId: IFieldFormatId, params: Record<string, any> = {}): FieldFormat => {
const DerivedFieldFormat = this.getType(formatId);
const ConcreteFieldFormat = this.getType(formatId);
if (!DerivedFieldFormat) {
if (!ConcreteFieldFormat) {
throw new Error(`Field Format '${formatId}' not found!`);
}
return new DerivedFieldFormat(params, this.getConfig);
}
return new ConcreteFieldFormat(params, this.getConfig);
},
(formatId: IFieldFormatId, params: Record<string, any>) =>
JSON.stringify({
formatId,
...params,
})
);
/**
@ -171,13 +173,7 @@ export class FieldFormatRegisty {
getDefaultInstancePlain(fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldFormat {
const conf = this.getDefaultConfig(fieldType, esTypes);
const DerivedFieldFormat = this.getType(conf.id);
if (!DerivedFieldFormat) {
throw new Error(`Field Format '${conf.id}' not found!`);
}
return new DerivedFieldFormat(conf.params, this.getConfig);
return this.getInstance(conf.id, conf.params);
}
/**
* Returns a cache key built by the given variables for caching in memoized
@ -233,11 +229,9 @@ export class FieldFormatRegisty {
});
}
register = (fieldFormats: IFieldFormatType[]) => {
register(fieldFormats: IFieldFormatType[]) {
fieldFormats.forEach(fieldFormat => this.fieldFormats.set(fieldFormat.id, fieldFormat));
return this;
};
}
/**
* FieldFormat decorator - provide a one way to add meta-params for all field formatters
@ -256,7 +250,7 @@ export class FieldFormatRegisty {
static id = fieldFormat.id;
static fieldType = fieldFormat.fieldType;
constructor(params: Record<string, any> = {}, getConfig?: Function) {
constructor(params: Record<string, any> = {}, getConfig?: GetConfigFn) {
super(getMetaParams(params), getConfig);
}
};
@ -268,16 +262,11 @@ export class FieldFormatRegisty {
/**
* 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,
},
...this.metaParamsOptions,
...customParams,
});
}

View file

@ -17,13 +17,6 @@
* under the License.
*/
export { HTML_CONTEXT_TYPE, TEXT_CONTEXT_TYPE } from './content_types';
export {
FieldFormat,
IFieldFormatType,
IFieldFormatId,
IFieldFormatMetaParams,
} from './field_format';
export { getHighlightRequest, asPrettyString, getHighlightHtml } from './utils';
export * from './converters';
export * from './constants';
import * as fieldFormats from './static';
export { fieldFormats };

View file

@ -17,10 +17,19 @@
* under the License.
*/
import { CoreSetup } from 'src/core/public';
import { FieldFormatRegisty } from './field_formats';
/**
* Everything the file exports is public
*/
import {
export { HTML_CONTEXT_TYPE, TEXT_CONTEXT_TYPE } from './content_types';
export { FieldFormat } from './field_format';
export { FieldFormatsRegistry } from './field_formats_registry';
export { getHighlightRequest, asPrettyString, getHighlightHtml } from './utils';
export { baseFormatters } from './constants/base_formatters';
export { DEFAULT_CONVERTER_COLOR } from './constants/color_default';
export {
BoolFormat,
BytesFormat,
ColorFormat,
@ -33,47 +42,17 @@ import {
RelativeDateFormat,
SourceFormat,
StaticLookupFormat,
UrlFormat,
StringFormat,
TruncateFormat,
UrlFormat,
} from '../../common/';
} from './converters';
export class FieldFormatsService {
private readonly fieldFormats: FieldFormatRegisty = new FieldFormatRegisty();
public setup(core: CoreSetup) {
this.fieldFormats.init(core);
this.fieldFormats.register([
BoolFormat,
BytesFormat,
ColorFormat,
DateFormat,
DateNanosFormat,
DurationFormat,
IpFormat,
NumberFormat,
PercentFormat,
RelativeDateFormat,
SourceFormat,
StaticLookupFormat,
StringFormat,
TruncateFormat,
UrlFormat,
]);
return this.fieldFormats as FieldFormatsSetup;
}
public start() {
return this.fieldFormats as FieldFormatsStart;
}
public stop() {
// nothing to do here yet
}
}
/** @public */
export type FieldFormatsSetup = Omit<FieldFormatRegisty, 'init'>;
export type FieldFormatsStart = Omit<FieldFormatRegisty, 'init' & 'register'>;
export {
GetConfigFn,
FIELD_FORMAT_IDS,
ContentType,
IFieldFormatConfig,
IFieldFormatType,
IFieldFormat,
IFieldFormatId,
} from './types';

View file

@ -17,11 +17,10 @@
* under the License.
*/
/** @public **/
export type ContentType = 'html' | 'text';
import { FieldFormat } from './field_format';
/** @public **/
export { IFieldFormat } from './field_format';
export type ContentType = 'html' | 'text';
/** @internal **/
export interface HtmlContextTypeOptions {
@ -66,3 +65,32 @@ export enum FIELD_FORMAT_IDS {
TRUNCATE = 'truncate',
URL = 'url',
}
export interface IFieldFormatConfig {
id: IFieldFormatId;
params: Record<string, any>;
es?: boolean;
}
export type GetConfigFn = <T = any>(key: string, defaultOverride?: T) => T;
export type IFieldFormat = PublicMethodsOf<FieldFormat>;
/**
* @string id type is needed for creating custom converters.
*/
export type IFieldFormatId = FIELD_FORMAT_IDS | string;
export type IFieldFormatType = (new (params?: any, getConfig?: GetConfigFn) => FieldFormat) & {
id: IFieldFormatId;
fieldType: string | string[];
};
export interface IFieldFormatMetaParams {
[key: string]: any;
parsedUrl?: {
origin: string;
pathname?: string;
basePath?: string;
};
}

View file

@ -17,7 +17,6 @@
* under the License.
*/
export * from './field_formats/types';
export * from './timefilter/types';
export * from './query/types';
export * from './kbn_field_types/types';

View file

@ -0,0 +1,55 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { CoreSetup } from 'src/core/public';
import { fieldFormats } from '../../common/field_formats';
export class FieldFormatsService {
private readonly fieldFormatsRegistry: fieldFormats.FieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry();
public setup(core: CoreSetup) {
core.uiSettings.getUpdate$().subscribe(({ key, newValue }) => {
if (key === 'format:defaultTypeMap') {
this.fieldFormatsRegistry.parseDefaultTypeMap(newValue);
}
});
const getConfig = core.uiSettings.get.bind(core.uiSettings);
this.fieldFormatsRegistry.init(getConfig, {
parsedUrl: {
origin: window.location.origin,
pathname: window.location.pathname,
basePath: core.http.basePath.get(),
},
});
return this.fieldFormatsRegistry as FieldFormatsSetup;
}
public start() {
return this.fieldFormatsRegistry as FieldFormatsStart;
}
}
/** @public */
export type FieldFormatsSetup = Pick<fieldFormats.FieldFormatsRegistry, 'register'>;
/** @public */
export type FieldFormatsStart = Omit<fieldFormats.FieldFormatsRegistry, 'init' & 'register'>;

View file

@ -17,5 +17,4 @@
* under the License.
*/
export { FieldFormatRegisty } from './field_formats'; // TODO: Try to remove
export { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats_service';

View file

@ -1,26 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { IFieldFormatId } from '../../common';
export interface FieldType {
id: IFieldFormatId;
params: Record<string, any>;
es?: boolean;
}

View file

@ -31,12 +31,6 @@ export function plugin(initializerContext: PluginInitializerContext) {
export { IRequestTypesMap, IResponseTypesMap } from './search';
export * from './types';
export {
// field formats
ContentType, // only used in agg_type
FIELD_FORMAT_IDS,
IFieldFormat,
IFieldFormatId,
IFieldFormatType,
// index patterns
IIndexPattern,
IFieldType,
@ -51,7 +45,7 @@ export {
TimeRange,
} from '../common';
export * from './field_formats_provider';
export * from './field_formats';
export * from './index_patterns';
export * from './search';
export * from './query';
@ -61,26 +55,7 @@ export {
esFilters,
esKuery,
esQuery,
// field formats
BoolFormat,
BytesFormat,
ColorFormat,
DateFormat,
DateNanosFormat,
DEFAULT_CONVERTER_COLOR,
DurationFormat,
FieldFormat,
getHighlightRequest, // only used in search source
IpFormat,
NumberFormat,
PercentFormat,
RelativeDateFormat,
SourceFormat,
StaticLookupFormat,
StringFormat,
TEXT_CONTEXT_TYPE, // only used in agg_types
TruncateFormat,
UrlFormat,
fieldFormats,
// index patterns
isFilterable,
// kbn field types

View file

@ -26,7 +26,7 @@ import {
IFieldType,
getKbnFieldType,
IFieldSubType,
FieldFormat,
fieldFormats,
shortenDottedString,
} from '../../../common';
@ -95,12 +95,12 @@ export class Field implements IFieldType {
let format = spec.format;
if (!FieldFormat.isInstanceOfFieldFormat(format)) {
const fieldFormats = getFieldFormats();
if (!fieldFormats.FieldFormat.isInstanceOfFieldFormat(format)) {
const fieldFormatsService = getFieldFormats();
format =
indexPattern.fieldFormatMap[spec.name] ||
fieldFormats.getDefaultInstance(spec.type, spec.esTypes);
fieldFormatsService.getDefaultInstance(spec.type, spec.esTypes);
}
const indexed = !!spec.indexed;

View file

@ -19,7 +19,7 @@
import _ from 'lodash';
import { IndexPattern } from './index_pattern';
import { ContentType } from '../../../common';
import { fieldFormats } from '../../../common';
const formattedCache = new WeakMap();
const partialFormattedCache = new WeakMap();
@ -31,7 +31,7 @@ export function formatHitProvider(indexPattern: IndexPattern, defaultFormat: any
hit: Record<string, any>,
val: any,
fieldName: string,
type: ContentType = 'html'
type: fieldFormats.ContentType = 'html'
) {
const field = indexPattern.fields.getByName(fieldName);
const format = field ? field.format : defaultFormat;

View file

@ -31,7 +31,7 @@ import { setNotifications, setFieldFormats } from '../../services';
// Temporary disable eslint, will be removed after moving to new platform folder
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { notificationServiceMock } from '../../../../../core/public/notifications/notifications_service.mock';
import { FieldFormatRegisty } from '../../field_formats_provider';
import { fieldFormats } from '../../../common/field_formats';
jest.mock('../../../../kibana_utils/public', () => {
const originalModule = jest.requireActual('../../../../kibana_utils/public');
@ -125,7 +125,7 @@ describe('IndexPattern', () => {
setNotifications(notifications);
setFieldFormats(({
getDefaultInstance: jest.fn(),
} as unknown) as FieldFormatRegisty);
} as unknown) as fieldFormats.FieldFormatsRegistry);
return create(indexPatternId).then((pattern: IndexPattern) => {
indexPattern = pattern;

View file

@ -17,11 +17,11 @@
* under the License.
*/
import {
FieldFormatRegisty,
Plugin,
FieldFormatsStart,
FieldFormatsSetup,
IndexPatternsContract,
fieldFormats,
} from '.';
import { searchSetupMock } from './search/mocks';
import { queryServiceMock } from './query/mocks';
@ -35,9 +35,8 @@ const autocompleteMock: any = {
hasQuerySuggestions: jest.fn(),
};
const fieldFormatsMock: PublicMethodsOf<FieldFormatRegisty> = {
const fieldFormatsMock: PublicMethodsOf<fieldFormats.FieldFormatsRegistry> = {
getByFieldType: jest.fn(),
getConfig: jest.fn(),
getDefaultConfig: jest.fn(),
getDefaultInstance: jest.fn() as any,
getDefaultInstanceCacheResolver: jest.fn(),

View file

@ -33,7 +33,7 @@ import {
} from './types';
import { AutocompleteService } from './autocomplete';
import { SearchService } from './search/search_service';
import { FieldFormatsService } from './field_formats_provider';
import { FieldFormatsService } from './field_formats';
import { QueryService } from './query';
import { createIndexPatternSelect } from './ui/index_pattern_select';
import { IndexPatterns } from './index_patterns';

View file

@ -73,7 +73,7 @@ import _ from 'lodash';
import { normalizeSortRequest } from './normalize_sort_request';
import { filterDocvalueFields } from './filter_docvalue_fields';
import { fieldWildcardFilter } from '../../../../kibana_utils/public';
import { getHighlightRequest, esFilters, esQuery, SearchRequest } from '../..';
import { fieldFormats, esFilters, esQuery, SearchRequest } from '../..';
import { SearchSourceOptions, SearchSourceFields } from './types';
import { fetchSoon, FetchOptions, RequestFailure } from '../fetch';
@ -382,7 +382,10 @@ export class SearchSource {
body.query = esQuery.buildEsQuery(index, query, filters, esQueryConfigs);
if (highlightAll && body.query) {
body.highlight = getHighlightRequest(body.query, getUiSettings().get('doc_table:highlight'));
body.highlight = fieldFormats.getHighlightRequest(
body.query,
getUiSettings().get('doc_table:highlight')
);
delete searchRequest.highlightAll;
}

View file

@ -21,7 +21,7 @@ import { CoreStart } from 'src/core/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { IUiActionsSetup, IUiActionsStart } from 'src/plugins/ui_actions/public';
import { AutocompleteSetup, AutocompleteStart } from './autocomplete/types';
import { FieldFormatsSetup, FieldFormatsStart } from './field_formats_provider';
import { FieldFormatsSetup, FieldFormatsStart } from './field_formats';
import { ISearchSetup, ISearchStart } from './search';
import { QuerySetup, QueryStart } from './query';
import { IndexPatternSelectProps } from './ui/index_pattern_select';

View file

@ -163,7 +163,6 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA
},
"fieldFormats": Object {
"getByFieldType": [MockFunction],
"getConfig": [MockFunction],
"getDefaultConfig": [MockFunction],
"getDefaultInstance": [MockFunction],
"getDefaultInstanceCacheResolver": [MockFunction],
@ -805,7 +804,6 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA
},
"fieldFormats": Object {
"getByFieldType": [MockFunction],
"getConfig": [MockFunction],
"getDefaultConfig": [MockFunction],
"getDefaultInstance": [MockFunction],
"getDefaultInstanceCacheResolver": [MockFunction],
@ -1429,7 +1427,6 @@ exports[`QueryStringInput Should pass the query language to the language switche
},
"fieldFormats": Object {
"getByFieldType": [MockFunction],
"getConfig": [MockFunction],
"getDefaultConfig": [MockFunction],
"getDefaultInstance": [MockFunction],
"getDefaultInstanceCacheResolver": [MockFunction],
@ -2068,7 +2065,6 @@ exports[`QueryStringInput Should pass the query language to the language switche
},
"fieldFormats": Object {
"getByFieldType": [MockFunction],
"getConfig": [MockFunction],
"getDefaultConfig": [MockFunction],
"getDefaultInstance": [MockFunction],
"getDefaultInstanceCacheResolver": [MockFunction],
@ -2692,7 +2688,6 @@ exports[`QueryStringInput Should render the given query 1`] = `
},
"fieldFormats": Object {
"getByFieldType": [MockFunction],
"getConfig": [MockFunction],
"getDefaultConfig": [MockFunction],
"getDefaultInstance": [MockFunction],
"getDefaultInstanceCacheResolver": [MockFunction],
@ -3331,7 +3326,6 @@ exports[`QueryStringInput Should render the given query 1`] = `
},
"fieldFormats": Object {
"getByFieldType": [MockFunction],
"getConfig": [MockFunction],
"getDefaultConfig": [MockFunction],
"getDefaultInstance": [MockFunction],
"getDefaultInstanceCacheResolver": [MockFunction],

View file

@ -0,0 +1,59 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { has } from 'lodash';
import { fieldFormats } from '../../common/field_formats';
import { IUiSettingsClient } from '../../../../core/server';
export class FieldFormatsService {
private readonly fieldFormatClasses: fieldFormats.IFieldFormatType[] =
fieldFormats.baseFormatters;
public setup() {
return {
register: (customFieldFormat: fieldFormats.IFieldFormatType) =>
this.fieldFormatClasses.push(customFieldFormat),
};
}
public start() {
return {
fieldFormatServiceFactory: async (uiSettings: IUiSettingsClient) => {
const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry();
const uiConfigs = await uiSettings.getAll();
const registeredUiSettings = uiSettings.getRegistered();
Object.keys(registeredUiSettings).forEach(key => {
if (has(uiConfigs, key) && registeredUiSettings[key].type === 'json') {
uiConfigs[key] = JSON.parse(uiConfigs[key]);
}
});
fieldFormatsRegistry.init((key: string) => uiConfigs[key], {}, this.fieldFormatClasses);
return fieldFormatsRegistry;
},
};
}
}
/** @public */
export type FieldFormatsSetup = ReturnType<FieldFormatsService['setup']>;
/** @public */
export type FieldFormatsStart = ReturnType<FieldFormatsService['start']>;

View file

@ -17,4 +17,4 @@
* under the License.
*/
export { DEFAULT_CONVERTER_COLOR } from './color_default';
export { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats_service';

View file

@ -18,7 +18,7 @@
*/
import { PluginInitializerContext } from '../../../core/server';
import { DataServerPlugin, DataPluginSetup } from './plugin';
import { DataServerPlugin, DataPluginSetup, DataPluginStart } from './plugin';
export function plugin(initializerContext: PluginInitializerContext) {
return new DataServerPlugin(initializerContext);
@ -29,14 +29,20 @@ export function plugin(initializerContext: PluginInitializerContext) {
* @public
*/
export { IRequestTypesMap, IResponseTypesMap } from './search';
export {
// field formats
FIELD_FORMAT_IDS,
IFieldFormat,
IFieldFormatId,
IFieldFormatType,
// es query
esFilters,
esKuery,
esQuery,
fieldFormats,
// kbn field types
castEsToKbnFieldTypeName,
getKbnFieldType,
getKbnTypeNames,
// index patterns
IIndexPattern,
isFilterable,
IFieldType,
IFieldSubType,
// kbn field types
@ -62,36 +68,11 @@ export {
shouldReadFieldFromDocValues,
indexPatterns,
} from './index_patterns';
export * from './search';
export {
// es query
esFilters,
esKuery,
esQuery,
// field formats
BoolFormat,
BytesFormat,
ColorFormat,
DateFormat,
DateNanosFormat,
DEFAULT_CONVERTER_COLOR,
DurationFormat,
FieldFormat,
IpFormat,
NumberFormat,
PercentFormat,
RelativeDateFormat,
SourceFormat,
StaticLookupFormat,
StringFormat,
TruncateFormat,
UrlFormat,
// index patterns
isFilterable,
// kbn field types
castEsToKbnFieldTypeName,
getKbnFieldType,
getKbnTypeNames,
} from '../common';
export { DataServerPlugin as Plugin, DataPluginSetup as PluginSetup };
export * from './search';
export {
DataServerPlugin as Plugin,
DataPluginSetup as PluginSetup,
DataPluginStart as PluginStart,
};

View file

@ -25,20 +25,28 @@ import { ScriptsService } from './scripts';
import { KqlTelemetryService } from './kql_telemetry';
import { UsageCollectionSetup } from '../../usage_collection/server';
import { AutocompleteService } from './autocomplete';
import { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats';
export interface DataPluginSetup {
search: ISearchSetup;
fieldFormats: FieldFormatsSetup;
}
export interface DataPluginStart {
fieldFormats: FieldFormatsStart;
}
export interface DataPluginSetupDependencies {
usageCollection?: UsageCollectionSetup;
}
export class DataServerPlugin implements Plugin<DataPluginSetup> {
export class DataServerPlugin implements Plugin<DataPluginSetup, DataPluginStart> {
private readonly searchService: SearchService;
private readonly scriptsService: ScriptsService;
private readonly kqlTelemetryService: KqlTelemetryService;
private readonly autocompleteService = new AutocompleteService();
private readonly indexPatterns = new IndexPatternsService();
private readonly fieldFormats = new FieldFormatsService();
constructor(initializerContext: PluginInitializerContext) {
this.searchService = new SearchService(initializerContext);
@ -53,11 +61,17 @@ export class DataServerPlugin implements Plugin<DataPluginSetup> {
this.kqlTelemetryService.setup(core, { usageCollection });
return {
fieldFormats: this.fieldFormats.setup(),
search: this.searchService.setup(core),
};
}
public start(core: CoreStart) {}
public start(core: CoreStart) {
return {
fieldFormats: this.fieldFormats.start(),
};
}
public stop() {}
}

View file

@ -17,48 +17,13 @@
* under the License.
*/
import { CoreSetup } from 'kibana/public';
import {
FieldFormatRegisty,
BoolFormat,
BytesFormat,
ColorFormat,
DateFormat,
DateNanosFormat,
DurationFormat,
IpFormat,
NumberFormat,
PercentFormat,
RelativeDateFormat,
SourceFormat,
StaticLookupFormat,
StringFormat,
TruncateFormat,
UrlFormat,
} from '../../plugins/data/public/';
import { fieldFormats } from '../../plugins/data/public';
export const getFieldFormatsRegistry = (core: CoreSetup) => {
const fieldFormats = new FieldFormatRegisty();
const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry();
const getConfig = core.uiSettings.get.bind(core.uiSettings);
fieldFormats.register([
BoolFormat,
BytesFormat,
ColorFormat,
DateFormat,
DateNanosFormat,
DurationFormat,
IpFormat,
NumberFormat,
PercentFormat,
RelativeDateFormat,
SourceFormat,
StaticLookupFormat,
StringFormat,
TruncateFormat,
UrlFormat,
]);
fieldFormatsRegistry.init(getConfig, {});
fieldFormats.init(core);
return fieldFormats;
return fieldFormatsRegistry;
};

View file

@ -22,12 +22,7 @@ import sinon from 'sinon';
// because it is one of the few places that we need to access the IndexPattern class itself, rather
// than just the type. Doing this as a temporary measure; it will be left behind when migrating to NP.
import {
FieldList,
FIELD_FORMAT_IDS,
IndexPattern,
indexPatterns,
} from '../../plugins/data/public';
import { FieldList, IndexPattern, indexPatterns, KBN_FIELD_TYPES } from '../../plugins/data/public';
import { setFieldFormats } from '../../plugins/data/public/services';
@ -62,7 +57,7 @@ export default function StubIndexPattern(pattern, getConfig, timeField, fields,
this.flattenHit = indexPatterns.flattenHitWrapper(this, this.metaFields);
this.formatHit = indexPatterns.formatHitProvider(
this,
registeredFieldFormats.getDefaultInstance(FIELD_FORMAT_IDS.STRING)
registeredFieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING)
);
this.fieldsFetcher = { apiClient: { baseUrl: '' } };
this.formatField = this.formatHit.formatField;

View file

@ -9,7 +9,7 @@ import { LensMultiTable } from '../types';
import React from 'react';
import { shallow } from 'enzyme';
import { MetricConfig } from './types';
import { FieldFormat } from '../../../../../../src/plugins/data/public';
import { fieldFormats } from '../../../../../../src/plugins/data/public';
function sampleArgs() {
const data: LensMultiTable = {
@ -54,8 +54,11 @@ describe('metric_expression', () => {
test('it renders the title and value', () => {
const { data, args } = sampleArgs();
expect(shallow(<MetricChart data={data} args={args} formatFactory={x => x as FieldFormat} />))
.toMatchInlineSnapshot(`
expect(
shallow(
<MetricChart data={data} args={args} formatFactory={x => x as fieldFormats.FieldFormat} />
)
).toMatchInlineSnapshot(`
<VisualizationContainer
className="lnsMetricExpression__container"
reportTitle="My fanci metric chart"
@ -95,7 +98,7 @@ describe('metric_expression', () => {
<MetricChart
data={data}
args={{ ...args, mode: 'reduced' }}
formatFactory={x => x as FieldFormat}
formatFactory={x => x as fieldFormats.FieldFormat}
/>
)
).toMatchInlineSnapshot(`

View file

@ -8,9 +8,7 @@ import Puid from 'puid';
import sinon from 'sinon';
import nodeCrypto from '@elastic/node-crypto';
import { CancellationToken } from '../../../common/cancellation_token';
import { FieldFormatsService } from '../../../../../../../src/legacy/ui/field_formats/mixin/field_formats_service';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { StringFormat } from '../../../../../../../src/plugins/data/server';
import { fieldFormats } from '../../../../../../../src/plugins/data/server';
import { LevelLogger } from '../../../server/lib/level_logger';
import { executeJobFactory } from './execute_job';
@ -76,8 +74,12 @@ describe('CSV Execute Job', function() {
uiConfigMock['format:defaultTypeMap'] = {
_default_: { id: 'string', params: {} },
};
const getConfig = key => uiConfigMock[key];
return new FieldFormatsService([StringFormat], getConfig);
const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry();
fieldFormatsRegistry.init(key => uiConfigMock[key], {}, [fieldFormats.StringFormat]);
return fieldFormatsRegistry;
},
plugins: {
elasticsearch: {

View file

@ -5,17 +5,10 @@
*/
import { i18n } from '@kbn/i18n';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { KibanaRequest } from '../../../../../../../src/core/server';
import { CSV_JOB_TYPE } from '../../../common/constants';
import { cryptoFactory } from '../../../server/lib';
import {
ESQueueWorkerExecuteFn,
ExecuteJobFactory,
FieldFormats,
Logger,
ServerFacade,
} from '../../../types';
import { ESQueueWorkerExecuteFn, ExecuteJobFactory, Logger, ServerFacade } from '../../../types';
import { JobDocPayloadDiscoverCsv } from '../types';
import { fieldFormatMapFactory } from './lib/field_format_map';
import { createGenerateCsv } from './lib/generate_csv';
@ -94,7 +87,7 @@ export const executeJobFactory: ExecuteJobFactory<ESQueueWorkerExecuteFn<
const [formatsMap, uiSettings] = await Promise.all([
(async () => {
const fieldFormats = (await server.fieldFormatServiceFactory(uiConfig)) as FieldFormats;
const fieldFormats = await server.fieldFormatServiceFactory(uiConfig);
return fieldFormatMapFactory(indexPatternSavedObject, fieldFormats);
})(),
(async () => {

View file

@ -5,10 +5,8 @@
*/
import expect from '@kbn/expect';
import { FieldFormatsService } from '../../../../../../../../src/legacy/ui/field_formats/mixin/field_formats_service';
// Reporting uses an unconventional directory structure so the linter marks this as a violation
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { BytesFormat, NumberFormat } from '../../../../../../../../src/plugins/data/server';
import { fieldFormats } from '../../../../../../../../src/plugins/data/server';
import { fieldFormatMapFactory } from './field_format_map';
type ConfigValue = { number: { id: string; params: {} } } | string;
@ -31,12 +29,13 @@ describe('field format map', function() {
number: { id: 'number', params: {} },
};
configMock['format:number:defaultPattern'] = '0,0.[000]';
const getConfig = (key: string) => configMock[key];
const getConfig = ((key: string) => configMock[key]) as fieldFormats.GetConfigFn;
const testValue = '4000';
const fieldFormats = new FieldFormatsService([BytesFormat, NumberFormat], getConfig);
const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry();
fieldFormatsRegistry.init(getConfig, {}, [fieldFormats.BytesFormat, fieldFormats.NumberFormat]);
const formatMap = fieldFormatMapFactory(indexPatternSavedObject, fieldFormats);
const formatMap = fieldFormatMapFactory(indexPatternSavedObject, fieldFormatsRegistry);
it('should build field format map with entry per index pattern field', function() {
expect(formatMap.has('field1')).to.be(true);

View file

@ -5,7 +5,7 @@
*/
import _ from 'lodash';
import { FieldFormats } from '../../../../types';
import { fieldFormats } from '../../../../../../../../src/plugins/data/server';
interface IndexPatternSavedObject {
attributes: {
@ -25,7 +25,7 @@ interface IndexPatternSavedObject {
*/
export function fieldFormatMapFactory(
indexPatternSavedObject: IndexPatternSavedObject,
fieldFormats: FieldFormats
fieldFormatsRegistry: fieldFormats.FieldFormatsRegistry
) {
const formatsMap = new Map();
@ -33,10 +33,13 @@ export function fieldFormatMapFactory(
if (_.has(indexPatternSavedObject, 'attributes.fieldFormatMap')) {
const fieldFormatMap = JSON.parse(indexPatternSavedObject.attributes.fieldFormatMap);
Object.keys(fieldFormatMap).forEach(fieldName => {
const formatConfig = fieldFormatMap[fieldName];
const formatConfig: fieldFormats.IFieldFormatConfig = fieldFormatMap[fieldName];
if (!_.isEmpty(formatConfig)) {
formatsMap.set(fieldName, fieldFormats.getInstance(formatConfig));
formatsMap.set(
fieldName,
fieldFormatsRegistry.getInstance(formatConfig.id, formatConfig.params)
);
}
});
}
@ -45,7 +48,7 @@ export function fieldFormatMapFactory(
const indexFields = JSON.parse(_.get(indexPatternSavedObject, 'attributes.fields', '[]'));
indexFields.forEach((field: any) => {
if (!formatsMap.has(field.name)) {
formatsMap.set(field.name, fieldFormats.getDefaultInstance(field.type));
formatsMap.set(field.name, fieldFormatsRegistry.getDefaultInstance(field.type));
}
});

View file

@ -7,6 +7,7 @@
import { resolve } from 'path';
import { i18n } from '@kbn/i18n';
import { Legacy } from 'kibana';
import { IUiSettingsClient } from 'kibana/server';
import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants';
import { ReportingConfigOptions, ReportingPluginSpecOptions } from './types.d';
import { config as reportingConfig } from './config';
@ -17,10 +18,16 @@ import {
reportingPluginFactory,
} from './server/plugin';
import { PluginStart as DataPluginStart } from '../../../../src/plugins/data/server';
const kbToBase64Length = (kb: number) => {
return Math.floor((kb * 1024 * 8) / 6);
};
interface ReportingDeps {
data: DataPluginStart;
}
export const reporting = (kibana: any) => {
return new kibana.Plugin({
id: PLUGIN_ID,
@ -70,6 +77,14 @@ export const reporting = (kibana: any) => {
const pluginsSetup: ReportingSetupDeps = {
usageCollection: server.newPlatform.setup.plugins.usageCollection,
};
const fieldFormatServiceFactory = async (uiSettings: IUiSettingsClient) => {
const [, plugins] = await coreSetup.getStartServices();
const { fieldFormats } = (plugins as ReportingDeps).data;
return fieldFormats.fieldFormatServiceFactory(uiSettings);
};
const __LEGACY: LegacySetup = {
config: server.config,
info: server.info,
@ -80,9 +95,8 @@ export const reporting = (kibana: any) => {
security: server.plugins.security,
},
savedObjects: server.savedObjects,
fieldFormatServiceFactory,
uiSettingsServiceFactory: server.uiSettingsServiceFactory,
// @ts-ignore Property 'fieldFormatServiceFactory' does not exist on type 'Server'.
fieldFormatServiceFactory: server.fieldFormatServiceFactory,
};
const initializerContext = server.newPlatform.coreContext;

View file

@ -6,7 +6,6 @@
import { Legacy } from 'kibana';
import { CoreSetup, CoreStart, Plugin, LoggerFactory } from 'src/core/server';
import { IUiSettingsClient } from 'src/core/server';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { XPackMainPlugin } from '../../xpack_main/server/xpack_main';
// @ts-ignore
@ -18,6 +17,7 @@ import { checkLicenseFactory, getExportTypesRegistry, runValidations, LevelLogge
import { createBrowserDriverFactory } from './browsers';
import { registerReportingUsageCollector } from './usage';
import { logConfiguration } from '../log_configuration';
import { PluginStart as DataPluginStart } from '../../../../../src/plugins/data/server';
export interface ReportingInitializerContext {
logger: LoggerFactory;
@ -47,7 +47,7 @@ export interface LegacySetup {
route: Legacy.Server['route'];
savedObjects: Legacy.Server['savedObjects'];
uiSettingsServiceFactory: Legacy.Server['uiSettingsServiceFactory'];
fieldFormatServiceFactory: (uiConfig: IUiSettingsClient) => unknown;
fieldFormatServiceFactory: DataPluginStart['fieldFormats']['fieldFormatServiceFactory'];
}
export type ReportingPlugin = Plugin<

View file

@ -7,10 +7,7 @@
import { ResponseObject } from 'hapi';
import { EventEmitter } from 'events';
import { Legacy } from 'kibana';
import {
ElasticsearchPlugin,
CallCluster,
} from '../../../../src/legacy/core_plugins/elasticsearch';
import { CallCluster } from '../../../../src/legacy/core_plugins/elasticsearch';
import { CancellationToken } from './common/cancellation_token';
import { LevelLogger } from './server/lib/level_logger';
import { HeadlessChromiumDriverFactory } from './server/browsers/chromium/driver_factory';
@ -333,9 +330,3 @@ export interface InterceptedRequest {
frameId: string;
resourceType: string;
}
export interface FieldFormats {
getConfig: number;
getInstance: (config: any) => any;
getDefaultInstance: (key: string) => any;
}