Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

moving visualize/utils to new platform #56650

Merged
merged 19 commits into from
Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,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,
Expand Down Expand Up @@ -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);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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}`;
};
Original file line number Diff line number Diff line change
@@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this the same as the TimeRange type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And convertDateRangeToString looks like a function that could be exported as a utility from data/public/index, taking in a TimeRange and returning a string

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);
}
};
Original file line number Diff line number Diff line change
@@ -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}`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we re-export this from the top level of the data plugin?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider waiting for #57177

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ppisljar as #57177 got merged can we clean up this import? Not a blocker though

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;
Expand Down
149 changes: 7 additions & 142 deletions src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
};

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);
}
const createFormat = fieldFormats.serialize;
const getFormat: FormatFactory = (mapping?) => {
return npStart.plugins.data.fieldFormats.deserialize(mapping as any);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may be able to get rid of as any with !, or by doing if (mapping)

Suggested change
return npStart.plugins.data.fieldFormats.deserialize(mapping as any);
return mapping ? npStart.plugins.data.fieldFormats.deserialize(mapping) : undefined;

...or:

Suggested change
return npStart.plugins.data.fieldFormats.deserialize(mapping as any);
return npStart.plugins.data.fieldFormats.deserialize(mapping!);

};

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 };
Loading