mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
# Conflicts: # x-pack/plugins/translations/translations/ja-JP.json # x-pack/plugins/translations/translations/zh-CN.json
This commit is contained in:
parent
7dc756352a
commit
4d71322a15
23 changed files with 336 additions and 188 deletions
|
@ -20,21 +20,19 @@ import { get } from 'lodash';
|
|||
import moment from 'moment-timezone';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import { convertDateRangeToString, DateRangeKey } from './lib/date_range';
|
||||
import { BUCKET_TYPES } from './bucket_agg_types';
|
||||
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
|
||||
import { createFilterDateRange } from './create_filter/date_range';
|
||||
|
||||
import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public';
|
||||
|
||||
export { convertDateRangeToString, DateRangeKey };
|
||||
|
||||
const dateRangeTitle = i18n.translate('data.search.aggs.buckets.dateRangeTitle', {
|
||||
defaultMessage: 'Date Range',
|
||||
});
|
||||
|
||||
export interface DateRangeKey {
|
||||
from: number;
|
||||
to: number;
|
||||
}
|
||||
|
||||
export const dateRangeBucketAgg = new BucketAggType({
|
||||
name: BUCKET_TYPES.DATE_RANGE,
|
||||
title: dateRangeTitle,
|
||||
|
@ -106,16 +104,3 @@ export const dateRangeBucketAgg = new BucketAggType({
|
|||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const convertDateRangeToString = (
|
||||
{ from, to }: DateRangeKey,
|
||||
format: (val: any) => string
|
||||
) => {
|
||||
if (!from) {
|
||||
return 'Before ' + format(to);
|
||||
} else if (!to) {
|
||||
return 'After ' + format(from);
|
||||
} else {
|
||||
return format(from) + ' to ' + format(to);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,21 +20,19 @@
|
|||
import { noop, map, omit, isNull } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import { IpRangeKey, convertIPRangeToString } from './lib/ip_range';
|
||||
import { BucketAggType } from './_bucket_agg_type';
|
||||
import { BUCKET_TYPES } from './bucket_agg_types';
|
||||
|
||||
// @ts-ignore
|
||||
import { createFilterIpRange } from './create_filter/ip_range';
|
||||
import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public';
|
||||
export { IpRangeKey, convertIPRangeToString };
|
||||
|
||||
const ipRangeTitle = i18n.translate('data.search.aggs.buckets.ipRangeTitle', {
|
||||
defaultMessage: 'IPv4 Range',
|
||||
});
|
||||
|
||||
export type IpRangeKey =
|
||||
| { type: 'mask'; mask: string }
|
||||
| { type: 'range'; from: string; to: string };
|
||||
|
||||
export const ipRangeBucketAgg = new BucketAggType({
|
||||
name: BUCKET_TYPES.IP_RANGE,
|
||||
title: ipRangeTitle,
|
||||
|
@ -97,13 +95,3 @@ export const ipRangeBucketAgg = new BucketAggType({
|
|||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const convertIPRangeToString = (range: IpRangeKey, format: (val: any) => string) => {
|
||||
if (range.type === 'mask') {
|
||||
return format(range.mask);
|
||||
}
|
||||
const from = range.from ? format(range.from) : '-Infinity';
|
||||
const to = range.to ? format(range.to) : 'Infinity';
|
||||
|
||||
return `${from} to ${to}`;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 interface DateRangeKey {
|
||||
from: number;
|
||||
to: number;
|
||||
}
|
||||
|
||||
export const convertDateRangeToString = (
|
||||
{ from, to }: DateRangeKey,
|
||||
format: (val: any) => string
|
||||
) => {
|
||||
if (!from) {
|
||||
return 'Before ' + format(to);
|
||||
} else if (!to) {
|
||||
return 'After ' + format(from);
|
||||
} else {
|
||||
return format(from) + ' to ' + format(to);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 type IpRangeKey =
|
||||
| { type: 'mask'; mask: string }
|
||||
| { type: 'range'; from: string; to: string };
|
||||
|
||||
export const convertIPRangeToString = (range: IpRangeKey, format: (val: any) => string) => {
|
||||
if (range.type === 'mask') {
|
||||
return format(range.mask);
|
||||
}
|
||||
const from = range.from ? format(range.from) : '-Infinity';
|
||||
const to = range.to ? format(range.to) : 'Infinity';
|
||||
|
||||
return `${from} to ${to}`;
|
||||
};
|
|
@ -22,6 +22,10 @@ import { shallow } from 'enzyme';
|
|||
|
||||
import { Vis } from 'src/legacy/core_plugins/visualizations/public';
|
||||
import { MetricVisComponent, MetricVisComponentProps } from './metric_vis_component';
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import { fieldFormats } from '../../../../../plugins/data/public';
|
||||
import { identity } from 'lodash';
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
|
||||
|
@ -62,6 +66,12 @@ describe('MetricVisComponent', function() {
|
|||
return shallow(<MetricVisComponent {...props} />);
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
(npStart.plugins.data.fieldFormats.deserialize as jest.Mock).mockImplementation(() => {
|
||||
return new (fieldFormats.FieldFormat.from(identity))();
|
||||
});
|
||||
});
|
||||
|
||||
it('should render component', () => {
|
||||
expect(getComponent().exists()).toBe(true);
|
||||
});
|
||||
|
|
|
@ -44,6 +44,9 @@ describe('metric_vis - createMetricVisTypeDefinition', () => {
|
|||
(npStart.plugins.data.fieldFormats.getType as jest.Mock).mockImplementation(() => {
|
||||
return fieldFormats.UrlFormat;
|
||||
});
|
||||
(npStart.plugins.data.fieldFormats.deserialize as jest.Mock).mockImplementation(mapping => {
|
||||
return new fieldFormats.UrlFormat(mapping ? mapping.params : {});
|
||||
});
|
||||
});
|
||||
|
||||
const setup = () => {
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
*/
|
||||
|
||||
export { AggType, AggGroupNames, IAggConfig, IAggType, Schemas } from 'ui/agg_types';
|
||||
export { getFormat, getTableAggs } from 'ui/visualize/loader/pipeline_helpers/utilities';
|
||||
export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
|
||||
// @ts-ignore
|
||||
export { tabifyAggResponse } from 'ui/agg_response/tabify';
|
||||
// @ts-ignore
|
||||
export { buildHierarchicalData } from 'ui/agg_response/hierarchical/build_hierarchical_data';
|
||||
// @ts-ignore
|
||||
export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series';
|
||||
export { tabifyGetColumns } from '../../../ui/public/agg_response/tabify/_get_columns';
|
||||
|
|
|
@ -22,14 +22,24 @@ import { compact, uniq, map } from 'lodash';
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiPopoverProps, EuiIcon, keyCodes, htmlIdGenerator } from '@elastic/eui';
|
||||
import { IAggConfig } from '../../../../../data/public';
|
||||
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { createFiltersFromEvent } from '../../../../../data/public/actions/filters/create_filters_from_event';
|
||||
import { CUSTOM_LEGEND_VIS_TYPES, LegendItem } from './models';
|
||||
import { VisLegendItem } from './legend_item';
|
||||
import { getPieNames } from './pie_utils';
|
||||
import { getTableAggs } from '../../../legacy_imports';
|
||||
|
||||
import { Vis } from '../../../../../visualizations/public';
|
||||
import { tabifyGetColumns } from '../../../legacy_imports';
|
||||
|
||||
const getTableAggs = (vis: Vis): IAggConfig[] => {
|
||||
if (!vis.aggs || !vis.aggs.getResponseAggs) {
|
||||
return [];
|
||||
}
|
||||
const columns = tabifyGetColumns(vis.aggs.getResponseAggs(), !vis.isHierarchical());
|
||||
return columns.map(c => c.aggConfig);
|
||||
};
|
||||
|
||||
export interface VisLegendProps {
|
||||
vis: any;
|
||||
|
|
|
@ -17,150 +17,15 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { identity } from 'lodash';
|
||||
import { IAggConfig } from 'ui/agg_types';
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import { SerializedFieldFormat } from 'src/plugins/expressions/public';
|
||||
import {
|
||||
fieldFormats,
|
||||
IFieldFormat,
|
||||
FieldFormatId,
|
||||
FieldFormatsContentType,
|
||||
} from '../../../../../../plugins/data/public';
|
||||
import { Vis } from '../../../../../core_plugins/visualizations/public';
|
||||
import { fieldFormats, IFieldFormat } from '../../../../../../plugins/data/public';
|
||||
import { SerializedFieldFormat } from '../../../../../../plugins/expressions/common/types';
|
||||
|
||||
import { tabifyGetColumns } from '../../../agg_response/tabify/_get_columns';
|
||||
import { DateRangeKey, convertDateRangeToString } from '../../../agg_types';
|
||||
import { IpRangeKey, convertIPRangeToString } from '../../../agg_types';
|
||||
type FormatFactory = (mapping?: SerializedFieldFormat) => IFieldFormat;
|
||||
|
||||
interface TermsFieldFormatParams {
|
||||
otherBucketLabel: string;
|
||||
missingBucketLabel: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
function isTermsFieldFormat(
|
||||
serializedFieldFormat: SerializedFieldFormat
|
||||
): serializedFieldFormat is SerializedFieldFormat<TermsFieldFormatParams> {
|
||||
return serializedFieldFormat.id === 'terms';
|
||||
}
|
||||
|
||||
const getConfig = (key: string, defaultOverride?: any): any =>
|
||||
npStart.core.uiSettings.get(key, defaultOverride);
|
||||
const DefaultFieldFormat = fieldFormats.FieldFormat.from(identity);
|
||||
|
||||
const getFieldFormat = (id?: FieldFormatId, params: object = {}): IFieldFormat => {
|
||||
const fieldFormatsService = npStart.plugins.data.fieldFormats;
|
||||
|
||||
if (id) {
|
||||
const Format = fieldFormatsService.getType(id);
|
||||
|
||||
if (Format) {
|
||||
return new Format(params, getConfig);
|
||||
}
|
||||
}
|
||||
|
||||
return new DefaultFieldFormat();
|
||||
const createFormat = fieldFormats.serialize;
|
||||
const getFormat: FormatFactory = (mapping?) => {
|
||||
return npStart.plugins.data.fieldFormats.deserialize(mapping as any);
|
||||
};
|
||||
|
||||
export const createFormat = (agg: IAggConfig): SerializedFieldFormat => {
|
||||
const format: SerializedFieldFormat = agg.params.field ? agg.params.field.format.toJSON() : {};
|
||||
const formats: Record<string, () => SerializedFieldFormat> = {
|
||||
date_range: () => ({ id: 'date_range', params: format }),
|
||||
ip_range: () => ({ id: 'ip_range', params: format }),
|
||||
percentile_ranks: () => ({ id: 'percent' }),
|
||||
count: () => ({ id: 'number' }),
|
||||
cardinality: () => ({ id: 'number' }),
|
||||
date_histogram: () => ({
|
||||
id: 'date',
|
||||
params: {
|
||||
pattern: (agg as any).buckets.getScaledDateFormat(),
|
||||
},
|
||||
}),
|
||||
terms: () => ({
|
||||
id: 'terms',
|
||||
params: {
|
||||
id: format.id,
|
||||
otherBucketLabel: agg.params.otherBucketLabel,
|
||||
missingBucketLabel: agg.params.missingBucketLabel,
|
||||
...format.params,
|
||||
},
|
||||
}),
|
||||
range: () => ({
|
||||
id: 'range',
|
||||
params: { id: format.id, ...format.params },
|
||||
}),
|
||||
};
|
||||
|
||||
return formats[agg.type.name] ? formats[agg.type.name]() : format;
|
||||
};
|
||||
|
||||
export type FormatFactory = (mapping?: SerializedFieldFormat) => IFieldFormat;
|
||||
|
||||
export const getFormat: FormatFactory = mapping => {
|
||||
if (!mapping) {
|
||||
return new DefaultFieldFormat();
|
||||
}
|
||||
const { id } = mapping;
|
||||
if (id === 'range') {
|
||||
const RangeFormat = fieldFormats.FieldFormat.from((range: any) => {
|
||||
const format = getFieldFormat(id, mapping.params);
|
||||
const gte = '\u2265';
|
||||
const lt = '\u003c';
|
||||
return i18n.translate('common.ui.aggTypes.rangesFormatMessage', {
|
||||
defaultMessage: '{gte} {from} and {lt} {to}',
|
||||
values: {
|
||||
gte,
|
||||
from: format.convert(range.gte),
|
||||
lt,
|
||||
to: format.convert(range.lt),
|
||||
},
|
||||
});
|
||||
});
|
||||
return new RangeFormat();
|
||||
} else if (id === 'date_range') {
|
||||
const nestedFormatter = mapping.params as SerializedFieldFormat;
|
||||
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 = 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: FieldFormatsContentType) => {
|
||||
const format = getFieldFormat(params.id, mapping.params);
|
||||
|
||||
if (val === '__other__') {
|
||||
return params.otherBucketLabel;
|
||||
}
|
||||
if (val === '__missing__') {
|
||||
return params.missingBucketLabel;
|
||||
}
|
||||
|
||||
return format.convert(val, type);
|
||||
};
|
||||
|
||||
return {
|
||||
convert,
|
||||
getConverterFor: (type: FieldFormatsContentType) => (val: string) => convert(val, type),
|
||||
} as IFieldFormat;
|
||||
} else {
|
||||
return getFieldFormat(id, mapping.params);
|
||||
}
|
||||
};
|
||||
|
||||
export const getTableAggs = (vis: Vis): IAggConfig[] => {
|
||||
if (!vis.aggs || !vis.aggs.getResponseAggs) {
|
||||
return [];
|
||||
}
|
||||
const columns = tabifyGetColumns(vis.aggs.getResponseAggs(), !vis.isHierarchical());
|
||||
return columns.map(c => c.aggConfig);
|
||||
};
|
||||
export { getFormat, createFormat, FormatFactory };
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
*/
|
||||
|
||||
// eslint-disable-next-line max-classes-per-file
|
||||
import { forOwn, isFunction, memoize } from 'lodash';
|
||||
import { forOwn, isFunction, memoize, identity } from 'lodash';
|
||||
|
||||
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../common';
|
||||
import { ES_FIELD_TYPES, IFieldFormat, KBN_FIELD_TYPES } from '../../common';
|
||||
|
||||
import {
|
||||
FieldFormatsGetConfigFn,
|
||||
|
@ -32,12 +32,17 @@ import {
|
|||
} from './types';
|
||||
import { baseFormatters } from './constants/base_formatters';
|
||||
import { FieldFormat } from './field_format';
|
||||
import { SerializedFieldFormat } from '../../../expressions/common/types';
|
||||
|
||||
export class FieldFormatsRegistry {
|
||||
protected fieldFormats: Map<FieldFormatId, IFieldFormatType> = new Map();
|
||||
protected defaultMap: Record<string, FieldFormatConfig> = {};
|
||||
protected metaParamsOptions: Record<string, any> = {};
|
||||
protected getConfig?: FieldFormatsGetConfigFn;
|
||||
// overriden on the public contract
|
||||
public deserialize: (mapping: SerializedFieldFormat) => IFieldFormat = () => {
|
||||
return new (FieldFormat.from(identity))();
|
||||
};
|
||||
|
||||
init(
|
||||
getConfig: FieldFormatsGetConfigFn,
|
||||
|
|
|
@ -41,7 +41,7 @@ export {
|
|||
TruncateFormat,
|
||||
} from './converters';
|
||||
|
||||
export { getHighlightRequest } from './utils';
|
||||
export { getHighlightRequest, serializeFieldFormat } from './utils';
|
||||
|
||||
export { DEFAULT_CONVERTER_COLOR } from './constants/color_default';
|
||||
export { FIELD_FORMAT_IDS } from './types';
|
||||
|
|
|
@ -17,5 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { SerializedFieldFormat } from '../../../../expressions/common/types';
|
||||
import { IFieldFormat } from '../index';
|
||||
|
||||
export { asPrettyString } from './as_pretty_string';
|
||||
export { getHighlightHtml, getHighlightRequest } from './highlight';
|
||||
export { serializeFieldFormat } from './serialize';
|
||||
|
||||
export type FormatFactory = (mapping?: SerializedFieldFormat) => IFieldFormat;
|
||||
|
|
53
src/plugins/data/common/field_formats/utils/serialize.ts
Normal file
53
src/plugins/data/common/field_formats/utils/serialize.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 { IAggConfig } from '../../../../../legacy/ui/public/agg_types';
|
||||
import { SerializedFieldFormat } from '../../../../expressions/common/types';
|
||||
|
||||
export const serializeFieldFormat = (agg: IAggConfig): SerializedFieldFormat => {
|
||||
const format: SerializedFieldFormat = agg.params.field ? agg.params.field.format.toJSON() : {};
|
||||
const formats: Record<string, () => SerializedFieldFormat> = {
|
||||
date_range: () => ({ id: 'date_range', params: format }),
|
||||
ip_range: () => ({ id: 'ip_range', params: format }),
|
||||
percentile_ranks: () => ({ id: 'percent' }),
|
||||
count: () => ({ id: 'number' }),
|
||||
cardinality: () => ({ id: 'number' }),
|
||||
date_histogram: () => ({
|
||||
id: 'date',
|
||||
params: {
|
||||
pattern: (agg as any).buckets.getScaledDateFormat(),
|
||||
},
|
||||
}),
|
||||
terms: () => ({
|
||||
id: 'terms',
|
||||
params: {
|
||||
id: format.id,
|
||||
otherBucketLabel: agg.params.otherBucketLabel,
|
||||
missingBucketLabel: agg.params.missingBucketLabel,
|
||||
...format.params,
|
||||
},
|
||||
}),
|
||||
range: () => ({
|
||||
id: 'range',
|
||||
params: { id: format.id, ...format.params },
|
||||
}),
|
||||
};
|
||||
|
||||
return formats[agg.type.name] ? formats[agg.type.name]() : format;
|
||||
};
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
import { CoreSetup } from 'src/core/public';
|
||||
import { FieldFormatsRegistry } from '../../common/field_formats';
|
||||
import { deserializeFieldFormat } from './utils/deserialize';
|
||||
import { FormatFactory } from '../../common/field_formats/utils';
|
||||
|
||||
export class FieldFormatsService {
|
||||
private readonly fieldFormatsRegistry: FieldFormatsRegistry = new FieldFormatsRegistry();
|
||||
|
@ -44,6 +46,10 @@ export class FieldFormatsService {
|
|||
}
|
||||
|
||||
public start() {
|
||||
this.fieldFormatsRegistry.deserialize = deserializeFieldFormat.bind(
|
||||
this.fieldFormatsRegistry as FieldFormatsStart
|
||||
);
|
||||
|
||||
return this.fieldFormatsRegistry as FieldFormatsStart;
|
||||
}
|
||||
}
|
||||
|
@ -52,4 +58,6 @@ export class FieldFormatsService {
|
|||
export type FieldFormatsSetup = Pick<FieldFormatsRegistry, 'register'>;
|
||||
|
||||
/** @public */
|
||||
export type FieldFormatsStart = Omit<FieldFormatsRegistry, 'init' & 'register'>;
|
||||
export type FieldFormatsStart = Omit<FieldFormatsRegistry, 'init' & 'register'> & {
|
||||
deserialize: FormatFactory;
|
||||
};
|
||||
|
|
129
src/plugins/data/public/field_formats/utils/deserialize.ts
Normal file
129
src/plugins/data/public/field_formats/utils/deserialize.ts
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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 { identity } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
convertDateRangeToString,
|
||||
DateRangeKey,
|
||||
} from '../../../../../legacy/core_plugins/data/public/search/aggs/buckets/lib/date_range';
|
||||
import {
|
||||
convertIPRangeToString,
|
||||
IpRangeKey,
|
||||
} from '../../../../../legacy/core_plugins/data/public/search/aggs/buckets/lib/ip_range';
|
||||
import { SerializedFieldFormat } from '../../../../expressions/common/types';
|
||||
import { FieldFormatId, FieldFormatsContentType, IFieldFormat } from '../..';
|
||||
import { FieldFormat } from '../../../common';
|
||||
import { DataPublicPluginStart } from '../../../public';
|
||||
import { getUiSettings } from '../../../public/services';
|
||||
import { FormatFactory } from '../../../common/field_formats/utils';
|
||||
|
||||
interface TermsFieldFormatParams {
|
||||
otherBucketLabel: string;
|
||||
missingBucketLabel: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
function isTermsFieldFormat(
|
||||
serializedFieldFormat: SerializedFieldFormat
|
||||
): serializedFieldFormat is SerializedFieldFormat<TermsFieldFormatParams> {
|
||||
return serializedFieldFormat.id === 'terms';
|
||||
}
|
||||
|
||||
const getConfig = (key: string, defaultOverride?: any): any =>
|
||||
getUiSettings().get(key, defaultOverride);
|
||||
const DefaultFieldFormat = FieldFormat.from(identity);
|
||||
|
||||
const getFieldFormat = (
|
||||
fieldFormatsService: DataPublicPluginStart['fieldFormats'],
|
||||
id?: FieldFormatId,
|
||||
params: object = {}
|
||||
): IFieldFormat => {
|
||||
if (id) {
|
||||
const Format = fieldFormatsService.getType(id);
|
||||
|
||||
if (Format) {
|
||||
return new Format(params, getConfig);
|
||||
}
|
||||
}
|
||||
|
||||
return new DefaultFieldFormat();
|
||||
};
|
||||
|
||||
export const deserializeFieldFormat: FormatFactory = function(
|
||||
this: DataPublicPluginStart['fieldFormats'],
|
||||
mapping?: SerializedFieldFormat
|
||||
) {
|
||||
if (!mapping) {
|
||||
return new DefaultFieldFormat();
|
||||
}
|
||||
const { id } = mapping;
|
||||
if (id === 'range') {
|
||||
const RangeFormat = FieldFormat.from((range: any) => {
|
||||
const format = getFieldFormat(this, id, mapping.params);
|
||||
const gte = '\u2265';
|
||||
const lt = '\u003c';
|
||||
return i18n.translate('data.aggTypes.buckets.ranges.rangesFormatMessage', {
|
||||
defaultMessage: '{gte} {from} and {lt} {to}',
|
||||
values: {
|
||||
gte,
|
||||
from: format.convert(range.gte),
|
||||
lt,
|
||||
to: format.convert(range.lt),
|
||||
},
|
||||
});
|
||||
});
|
||||
return new RangeFormat();
|
||||
} else if (id === 'date_range') {
|
||||
const nestedFormatter = mapping.params as SerializedFieldFormat;
|
||||
const DateRangeFormat = FieldFormat.from((range: DateRangeKey) => {
|
||||
const format = getFieldFormat(this, 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 format = getFieldFormat(this, 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: FieldFormatsContentType) => {
|
||||
const format = getFieldFormat(this, params.id, mapping.params);
|
||||
|
||||
if (val === '__other__') {
|
||||
return params.otherBucketLabel;
|
||||
}
|
||||
if (val === '__missing__') {
|
||||
return params.missingBucketLabel;
|
||||
}
|
||||
|
||||
return format.convert(val, type);
|
||||
};
|
||||
|
||||
return {
|
||||
convert,
|
||||
getConverterFor: (type: FieldFormatsContentType) => (val: string) => convert(val, type),
|
||||
} as IFieldFormat;
|
||||
} else {
|
||||
return getFieldFormat(this, id, mapping.params);
|
||||
}
|
||||
};
|
|
@ -168,6 +168,7 @@ import {
|
|||
UrlFormat,
|
||||
StringFormat,
|
||||
TruncateFormat,
|
||||
serializeFieldFormat,
|
||||
} from '../common/field_formats';
|
||||
|
||||
// Field formats helpers namespace:
|
||||
|
@ -175,6 +176,8 @@ export const fieldFormats = {
|
|||
FieldFormat,
|
||||
FieldFormatsRegistry, // exported only for tests. Consider mock.
|
||||
|
||||
serialize: serializeFieldFormat,
|
||||
|
||||
DEFAULT_CONVERTER_COLOR,
|
||||
HTML_CONTEXT_TYPE,
|
||||
TEXT_CONTEXT_TYPE,
|
||||
|
|
|
@ -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 { FieldFormatsRegistry } from '../../../common/field_formats';
|
||||
import { FieldFormatsStart } from '../../field_formats';
|
||||
|
||||
jest.mock('../../../../kibana_utils/public', () => {
|
||||
const originalModule = jest.requireActual('../../../../kibana_utils/public');
|
||||
|
@ -125,7 +125,8 @@ describe('IndexPattern', () => {
|
|||
setNotifications(notifications);
|
||||
setFieldFormats(({
|
||||
getDefaultInstance: jest.fn(),
|
||||
} as unknown) as FieldFormatsRegistry);
|
||||
deserialize: jest.fn() as any,
|
||||
} as unknown) as FieldFormatsStart);
|
||||
|
||||
return create(indexPatternId).then((pattern: IndexPattern) => {
|
||||
indexPattern = pattern;
|
||||
|
|
|
@ -49,6 +49,7 @@ const fieldFormatsMock: IFieldFormatsRegistry = {
|
|||
init: jest.fn(),
|
||||
register: jest.fn(),
|
||||
parseDefaultTypeMap: jest.fn(),
|
||||
deserialize: jest.fn(),
|
||||
};
|
||||
|
||||
const createSetupContract = (): Setup => {
|
||||
|
|
|
@ -173,6 +173,7 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA
|
|||
"hasQuerySuggestions": [MockFunction],
|
||||
},
|
||||
"fieldFormats": Object {
|
||||
"deserialize": [MockFunction],
|
||||
"getByFieldType": [MockFunction],
|
||||
"getDefaultConfig": [MockFunction],
|
||||
"getDefaultInstance": [MockFunction],
|
||||
|
@ -825,6 +826,7 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA
|
|||
"hasQuerySuggestions": [MockFunction],
|
||||
},
|
||||
"fieldFormats": Object {
|
||||
"deserialize": [MockFunction],
|
||||
"getByFieldType": [MockFunction],
|
||||
"getDefaultConfig": [MockFunction],
|
||||
"getDefaultInstance": [MockFunction],
|
||||
|
@ -1459,6 +1461,7 @@ exports[`QueryStringInput Should pass the query language to the language switche
|
|||
"hasQuerySuggestions": [MockFunction],
|
||||
},
|
||||
"fieldFormats": Object {
|
||||
"deserialize": [MockFunction],
|
||||
"getByFieldType": [MockFunction],
|
||||
"getDefaultConfig": [MockFunction],
|
||||
"getDefaultInstance": [MockFunction],
|
||||
|
@ -2108,6 +2111,7 @@ exports[`QueryStringInput Should pass the query language to the language switche
|
|||
"hasQuerySuggestions": [MockFunction],
|
||||
},
|
||||
"fieldFormats": Object {
|
||||
"deserialize": [MockFunction],
|
||||
"getByFieldType": [MockFunction],
|
||||
"getDefaultConfig": [MockFunction],
|
||||
"getDefaultInstance": [MockFunction],
|
||||
|
@ -2742,6 +2746,7 @@ exports[`QueryStringInput Should render the given query 1`] = `
|
|||
"hasQuerySuggestions": [MockFunction],
|
||||
},
|
||||
"fieldFormats": Object {
|
||||
"deserialize": [MockFunction],
|
||||
"getByFieldType": [MockFunction],
|
||||
"getDefaultConfig": [MockFunction],
|
||||
"getDefaultInstance": [MockFunction],
|
||||
|
@ -3391,6 +3396,7 @@ exports[`QueryStringInput Should render the given query 1`] = `
|
|||
"hasQuerySuggestions": [MockFunction],
|
||||
},
|
||||
"fieldFormats": Object {
|
||||
"deserialize": [MockFunction],
|
||||
"getByFieldType": [MockFunction],
|
||||
"getDefaultConfig": [MockFunction],
|
||||
"getDefaultInstance": [MockFunction],
|
||||
|
|
|
@ -95,12 +95,15 @@ import {
|
|||
UrlFormat,
|
||||
StringFormat,
|
||||
TruncateFormat,
|
||||
serializeFieldFormat,
|
||||
} from '../common/field_formats';
|
||||
|
||||
export const fieldFormats = {
|
||||
FieldFormatsRegistry,
|
||||
FieldFormat,
|
||||
|
||||
serializeFieldFormat,
|
||||
|
||||
BoolFormat,
|
||||
BytesFormat,
|
||||
ColorFormat,
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { CoreSetup } from 'kibana/public';
|
||||
import { fieldFormats } from '../../plugins/data/public';
|
||||
import { DataPublicPluginStart, fieldFormats } from '../../plugins/data/public';
|
||||
import { deserializeFieldFormat } from '../../plugins/data/public/field_formats/utils/deserialize';
|
||||
|
||||
export const getFieldFormatsRegistry = (core: CoreSetup) => {
|
||||
const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry();
|
||||
|
@ -25,5 +26,9 @@ export const getFieldFormatsRegistry = (core: CoreSetup) => {
|
|||
|
||||
fieldFormatsRegistry.init(getConfig, {});
|
||||
|
||||
fieldFormatsRegistry.deserialize = deserializeFieldFormat.bind(
|
||||
fieldFormatsRegistry as DataPublicPluginStart['fieldFormats']
|
||||
);
|
||||
|
||||
return fieldFormatsRegistry;
|
||||
};
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
},
|
||||
"messages": {
|
||||
"common.ui.aggResponse.allDocsTitle": "すべてのドキュメント",
|
||||
"common.ui.aggTypes.rangesFormatMessage": "{gte} {from} と {lt} {to}",
|
||||
"data.search.aggs.aggGroups.bucketsText": "バケット",
|
||||
"data.search.aggs.aggGroups.metricsText": "メトリック",
|
||||
"data.search.aggs.buckets.dateHistogramLabel": "{intervalDescription}ごとの {fieldName}",
|
||||
|
@ -13844,4 +13843,4 @@
|
|||
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。",
|
||||
"xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
},
|
||||
"messages": {
|
||||
"common.ui.aggResponse.allDocsTitle": "所有文档",
|
||||
"common.ui.aggTypes.rangesFormatMessage": "{gte} {from} 且 {lt} {to}",
|
||||
"data.search.aggs.aggGroups.bucketsText": "存储桶",
|
||||
"data.search.aggs.aggGroups.metricsText": "指标",
|
||||
"data.search.aggs.buckets.dateHistogramLabel": "{fieldName}/{intervalDescription}",
|
||||
|
@ -13843,4 +13842,4 @@
|
|||
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。",
|
||||
"xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue