+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
{},
closeNav: () => {},
navigateToApp: () => Promise.resolve(),
+ customNavLink$: new BehaviorSubject(undefined),
};
}
@@ -120,12 +121,14 @@ describe('CollapsibleNav', () => {
mockRecentNavLink({ label: 'recent 1' }),
mockRecentNavLink({ label: 'recent 2' }),
];
+ const customNavLink = mockLink({ title: 'Custom link' });
const component = mount(
);
expect(component).toMatchSnapshot();
diff --git a/src/core/public/chrome/ui/header/collapsible_nav.tsx b/src/core/public/chrome/ui/header/collapsible_nav.tsx
index 9494e22920de8..07541b1adff16 100644
--- a/src/core/public/chrome/ui/header/collapsible_nav.tsx
+++ b/src/core/public/chrome/ui/header/collapsible_nav.tsx
@@ -30,7 +30,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { groupBy, sortBy } from 'lodash';
-import React, { useRef } from 'react';
+import React, { Fragment, useRef } from 'react';
import { useObservable } from 'react-use';
import * as Rx from 'rxjs';
import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../..';
@@ -88,6 +88,7 @@ interface Props {
onIsLockedUpdate: OnIsLockedUpdate;
closeNav: () => void;
navigateToApp: InternalApplicationStart['navigateToApp'];
+ customNavLink$: Rx.Observable;
}
export function CollapsibleNav({
@@ -105,6 +106,7 @@ export function CollapsibleNav({
}: Props) {
const navLinks = useObservable(observables.navLinks$, []).filter((link) => !link.hidden);
const recentlyAccessed = useObservable(observables.recentlyAccessed$, []);
+ const customNavLink = useObservable(observables.customNavLink$, undefined);
const appId = useObservable(observables.appId$, '');
const lockRef = useRef(null);
const groupedNavLinks = groupBy(navLinks, (link) => link?.category?.id);
@@ -134,6 +136,38 @@ export function CollapsibleNav({
isDocked={isLocked}
onClose={closeNav}
>
+ {customNavLink && (
+
+
+
+
+
+
+
+
+
+ )}
+
{/* Pinned items */}
{
const navLinks$ = new BehaviorSubject([
{ id: 'kibana', title: 'kibana', baseUrl: '', legacy: false },
]);
+ const customNavLink$ = new BehaviorSubject({
+ id: 'cloud-deployment-link',
+ title: 'Manage cloud deployment',
+ baseUrl: '',
+ legacy: false,
+ });
const recentlyAccessed$ = new BehaviorSubject([
{ link: '', label: 'dashboard', id: 'dashboard' },
]);
@@ -87,6 +94,7 @@ describe('Header', () => {
recentlyAccessed$={recentlyAccessed$}
isLocked$={isLocked$}
navType$={navType$}
+ customNavLink$={customNavLink$}
/>
);
expect(component).toMatchSnapshot();
diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx
index d24b342e0386b..3da3caaaa4a4f 100644
--- a/src/core/public/chrome/ui/header/header.tsx
+++ b/src/core/public/chrome/ui/header/header.tsx
@@ -58,6 +58,7 @@ export interface HeaderProps {
appTitle$: Observable;
badge$: Observable;
breadcrumbs$: Observable;
+ customNavLink$: Observable;
homeHref: string;
isVisible$: Observable;
kibanaDocLink: string;
@@ -203,6 +204,7 @@ export function Header({
toggleCollapsibleNavRef.current.focus();
}
}}
+ customNavLink$={observables.customNavLink$}
/>
) : (
// TODO #64541
diff --git a/src/core/public/chrome/ui/header/nav_link.tsx b/src/core/public/chrome/ui/header/nav_link.tsx
index 969b6728e0263..6b5cecd138376 100644
--- a/src/core/public/chrome/ui/header/nav_link.tsx
+++ b/src/core/public/chrome/ui/header/nav_link.tsx
@@ -35,11 +35,12 @@ function LinkIcon({ url }: { url: string }) {
interface Props {
link: ChromeNavLink;
legacyMode: boolean;
- appId: string | undefined;
+ appId?: string;
basePath?: HttpStart['basePath'];
dataTestSubj: string;
onClick?: Function;
navigateToApp: CoreStart['application']['navigateToApp'];
+ externalLink?: boolean;
}
// TODO #64541
@@ -54,6 +55,7 @@ export function createEuiListItem({
onClick = () => {},
navigateToApp,
dataTestSubj,
+ externalLink = false,
}: Props) {
const { legacy, active, id, title, disabled, euiIconType, icon, tooltip } = link;
let { href } = link;
@@ -69,6 +71,7 @@ export function createEuiListItem({
onClick(event: React.MouseEvent) {
onClick();
if (
+ !externalLink && // ignore external links
!legacyMode && // ignore when in legacy mode
!legacy && // ignore links to legacy apps
!event.defaultPrevented && // onClick prevented default
diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts
index d6172b77d3ca5..00fabc2b6f2f1 100644
--- a/src/core/public/core_system.ts
+++ b/src/core/public/core_system.ts
@@ -163,7 +163,7 @@ export class CoreSystem {
i18n: this.i18n.getContext(),
});
await this.integrations.setup();
- const docLinks = this.docLinks.setup({ injectedMetadata });
+ this.docLinks.setup();
const http = this.http.setup({ injectedMetadata, fatalErrors: this.fatalErrorsSetup });
const uiSettings = this.uiSettings.setup({ http, injectedMetadata });
const notifications = this.notifications.setup({ uiSettings });
@@ -185,7 +185,6 @@ export class CoreSystem {
const core: InternalCoreSetup = {
application,
context,
- docLinks,
fatalErrors: this.fatalErrorsSetup,
http,
injectedMetadata,
@@ -217,7 +216,7 @@ export class CoreSystem {
try {
const injectedMetadata = await this.injectedMetadata.start();
const uiSettings = await this.uiSettings.start();
- const docLinks = this.docLinks.start();
+ const docLinks = this.docLinks.start({ injectedMetadata });
const http = await this.http.start();
const savedObjects = await this.savedObjects.start({ http });
const i18n = await this.i18n.start();
diff --git a/src/core/public/doc_links/doc_links_service.mock.ts b/src/core/public/doc_links/doc_links_service.mock.ts
index 9edcf2e3c7990..105c13f96cef6 100644
--- a/src/core/public/doc_links/doc_links_service.mock.ts
+++ b/src/core/public/doc_links/doc_links_service.mock.ts
@@ -18,25 +18,23 @@
*/
import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock';
-import { DocLinksService, DocLinksSetup, DocLinksStart } from './doc_links_service';
+import { DocLinksService, DocLinksStart } from './doc_links_service';
-const createSetupContractMock = (): DocLinksSetup => {
+const createStartContractMock = (): DocLinksStart => {
// This service is so simple that we actually use the real implementation
const injectedMetadata = injectedMetadataServiceMock.createStartContract();
injectedMetadata.getKibanaBranch.mockReturnValue('mocked-test-branch');
- return new DocLinksService().setup({ injectedMetadata });
+ return new DocLinksService().start({ injectedMetadata });
};
-const createStartContractMock: () => DocLinksStart = createSetupContractMock;
-
type DocLinksServiceContract = PublicMethodsOf;
const createMock = (): jest.Mocked => ({
- setup: jest.fn().mockReturnValue(createSetupContractMock()),
+ setup: jest.fn().mockReturnValue(undefined),
start: jest.fn().mockReturnValue(createStartContractMock()),
});
export const docLinksServiceMock = {
create: createMock,
- createSetupContract: createSetupContractMock,
+ createSetupContract: () => jest.fn(),
createStartContract: createStartContractMock,
};
diff --git a/src/core/public/doc_links/doc_links_service.test.ts b/src/core/public/doc_links/doc_links_service.test.ts
index 4c5d6bcde8b77..c430ae7655040 100644
--- a/src/core/public/doc_links/doc_links_service.test.ts
+++ b/src/core/public/doc_links/doc_links_service.test.ts
@@ -20,33 +20,15 @@
import { DocLinksService } from './doc_links_service';
import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock';
-describe('DocLinksService#setup()', () => {
+describe('DocLinksService#start()', () => {
it('templates the doc links with the branch information from injectedMetadata', () => {
const injectedMetadata = injectedMetadataServiceMock.createStartContract();
injectedMetadata.getKibanaBranch.mockReturnValue('test-branch');
const service = new DocLinksService();
- const setup = service.setup({ injectedMetadata });
- expect(setup.DOC_LINK_VERSION).toEqual('test-branch');
- expect(setup.links.kibana).toEqual(
+ const api = service.start({ injectedMetadata });
+ expect(api.DOC_LINK_VERSION).toEqual('test-branch');
+ expect(api.links.kibana).toEqual(
'https://www.elastic.co/guide/en/kibana/test-branch/index.html'
);
});
});
-
-describe('DocLinksService#start()', () => {
- it('returns the same data as setup', () => {
- const injectedMetadata = injectedMetadataServiceMock.createStartContract();
- injectedMetadata.getKibanaBranch.mockReturnValue('test-branch');
- const service = new DocLinksService();
- const setup = service.setup({ injectedMetadata });
- const start = service.start();
- expect(setup).toEqual(start);
- });
-
- it('must be called after setup', () => {
- const service = new DocLinksService();
- expect(() => {
- service.start();
- }).toThrowErrorMatchingInlineSnapshot(`"DocLinksService#setup() must be called first!"`);
- });
-});
diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts
index f2bc90a5b08d4..0662586797164 100644
--- a/src/core/public/doc_links/doc_links_service.ts
+++ b/src/core/public/doc_links/doc_links_service.ts
@@ -20,20 +20,19 @@
import { InjectedMetadataSetup } from '../injected_metadata';
import { deepFreeze } from '../../utils';
-interface SetupDeps {
+interface StartDeps {
injectedMetadata: InjectedMetadataSetup;
}
/** @internal */
export class DocLinksService {
- private service?: DocLinksSetup;
-
- public setup({ injectedMetadata }: SetupDeps): DocLinksSetup {
+ public setup() {}
+ public start({ injectedMetadata }: StartDeps): DocLinksStart {
const DOC_LINK_VERSION = injectedMetadata.getKibanaBranch();
const ELASTIC_WEBSITE_URL = 'https://www.elastic.co/';
const ELASTICSEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`;
- this.service = deepFreeze({
+ return deepFreeze({
DOC_LINK_VERSION,
ELASTIC_WEBSITE_URL,
links: {
@@ -129,21 +128,11 @@ export class DocLinksService {
},
},
});
-
- return this.service;
- }
-
- public start(): DocLinksStart {
- if (!this.service) {
- throw new Error(`DocLinksService#setup() must be called first!`);
- }
-
- return this.service;
}
}
/** @public */
-export interface DocLinksSetup {
+export interface DocLinksStart {
readonly DOC_LINK_VERSION: string;
readonly ELASTIC_WEBSITE_URL: string;
readonly links: {
@@ -236,6 +225,3 @@ export interface DocLinksSetup {
readonly management: Record;
};
}
-
-/** @public */
-export type DocLinksStart = DocLinksSetup;
diff --git a/src/core/public/doc_links/index.ts b/src/core/public/doc_links/index.ts
index fbfa9db5635dd..fe49d4a7c6a58 100644
--- a/src/core/public/doc_links/index.ts
+++ b/src/core/public/doc_links/index.ts
@@ -17,4 +17,4 @@
* under the License.
*/
-export { DocLinksService, DocLinksSetup, DocLinksStart } from './doc_links_service';
+export { DocLinksService, DocLinksStart } from './doc_links_service';
diff --git a/src/core/public/index.ts b/src/core/public/index.ts
index 99b75f85340f3..41af0f1b8395f 100644
--- a/src/core/public/index.ts
+++ b/src/core/public/index.ts
@@ -67,7 +67,7 @@ import { OverlayStart } from './overlays';
import { Plugin, PluginInitializer, PluginInitializerContext, PluginOpaqueId } from './plugins';
import { UiSettingsState, IUiSettingsClient } from './ui_settings';
import { ApplicationSetup, Capabilities, ApplicationStart } from './application';
-import { DocLinksSetup, DocLinksStart } from './doc_links';
+import { DocLinksStart } from './doc_links';
import { SavedObjectsStart } from './saved_objects';
export { PackageInfo, EnvironmentMode } from '../server/types';
import {
@@ -216,8 +216,6 @@ export interface CoreSetup {
mockSetupDeps = {
application: applicationServiceMock.createInternalSetupContract(),
context: contextServiceMock.createSetupContract(),
- docLinks: docLinksServiceMock.createSetupContract(),
fatalErrors: fatalErrorsServiceMock.createSetupContract(),
http: httpServiceMock.createSetupContract(),
injectedMetadata: pick(injectedMetadataServiceMock.createStartContract(), 'getInjectedVar'),
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index 7970d9f3f86bb..d10e351f4d13e 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -154,6 +154,7 @@ export function __kbnBootstrap__(): void;
export interface App extends AppBase {
appRoute?: string;
chromeless?: boolean;
+ exactRoute?: boolean;
mount: AppMount | AppMountDeprecated;
}
@@ -466,6 +467,7 @@ export interface ChromeStart {
getBadge$(): Observable;
getBrand$(): Observable;
getBreadcrumbs$(): Observable;
+ getCustomNavLink$(): Observable | undefined>;
getHelpExtension$(): Observable;
getIsNavDrawerLocked$(): Observable;
getIsVisible$(): Observable;
@@ -478,6 +480,7 @@ export interface ChromeStart {
setBadge(badge?: ChromeBadge): void;
setBrand(brand: ChromeBrand): void;
setBreadcrumbs(newBreadcrumbs: ChromeBreadcrumb[]): void;
+ setCustomNavLink(newCustomNavLink?: Partial): void;
setHelpExtension(helpExtension?: ChromeHelpExtension): void;
setHelpSupportUrl(url: string): void;
setIsVisible(isVisible: boolean): void;
@@ -508,8 +511,6 @@ export interface CoreSetup;
@@ -600,7 +601,7 @@ export const DEFAULT_APP_CATEGORIES: Readonly<{
}>;
// @public (undocumented)
-export interface DocLinksSetup {
+export interface DocLinksStart {
// (undocumented)
readonly DOC_LINK_VERSION: string;
// (undocumented)
@@ -697,9 +698,6 @@ export interface DocLinksSetup {
};
}
-// @public (undocumented)
-export type DocLinksStart = DocLinksSetup;
-
// @public (undocumented)
export interface EnvironmentMode {
// (undocumented)
@@ -1594,6 +1592,6 @@ export interface UserProvidedValues {
// Warnings were encountered during analysis:
//
-// src/core/public/core_system.ts:216:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts
+// src/core/public/core_system.ts:215:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts
```
diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts
index 1e0b631308d9e..065321e355256 100644
--- a/src/dev/typescript/projects.ts
+++ b/src/dev/typescript/projects.ts
@@ -34,6 +34,10 @@ export const PROJECTS = [
name: 'apm/cypress',
disableTypeCheck: true,
}),
+ new Project(resolve(REPO_ROOT, 'x-pack/plugins/apm/scripts/tsconfig.json'), {
+ name: 'apm/scripts',
+ disableTypeCheck: true,
+ }),
// NOTE: using glob.sync rather than glob-all or globby
// because it takes less than 10 ms, while the other modules
diff --git a/src/plugins/data/common/field_formats/index.ts b/src/plugins/data/common/field_formats/index.ts
index 5c67073c07dd5..104ff030873aa 100644
--- a/src/plugins/data/common/field_formats/index.ts
+++ b/src/plugins/data/common/field_formats/index.ts
@@ -40,7 +40,7 @@ export {
TruncateFormat,
} from './converters';
-export { getHighlightRequest, serializeFieldFormat } from './utils';
+export { getHighlightRequest } from './utils';
export { DEFAULT_CONVERTER_COLOR } from './constants/color_default';
export { FIELD_FORMAT_IDS } from './types';
diff --git a/src/plugins/data/common/field_formats/utils/index.ts b/src/plugins/data/common/field_formats/utils/index.ts
index 3832c941ffad7..eb020c17ca09c 100644
--- a/src/plugins/data/common/field_formats/utils/index.ts
+++ b/src/plugins/data/common/field_formats/utils/index.ts
@@ -22,6 +22,5 @@ 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;
diff --git a/src/plugins/data/common/field_formats/utils/serialize.ts b/src/plugins/data/common/field_formats/utils/serialize.ts
deleted file mode 100644
index 1092c90d19451..0000000000000
--- a/src/plugins/data/common/field_formats/utils/serialize.ts
+++ /dev/null
@@ -1,53 +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 { IAggConfig } from 'src/plugins/data/public';
-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 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;
-};
diff --git a/src/plugins/data/public/field_formats/utils/deserialize.ts b/src/plugins/data/public/field_formats/utils/deserialize.ts
index d9c713c8b1eb4..26baa5fdeb1e4 100644
--- a/src/plugins/data/public/field_formats/utils/deserialize.ts
+++ b/src/plugins/data/public/field_formats/utils/deserialize.ts
@@ -18,107 +18,42 @@
*/
import { identity } from 'lodash';
-import { i18n } from '@kbn/i18n';
-import { convertDateRangeToString, DateRangeKey } from '../../search/aggs/buckets/lib/date_range';
-import { convertIPRangeToString, IpRangeKey } from '../../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 {
- return serializedFieldFormat.id === 'terms';
-}
+import { DataPublicPluginStart, IFieldFormat } from '../../../public';
+import { getUiSettings } from '../../../public/services';
+import { getFormatWithAggs } from '../../search/aggs/utils';
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
+ serializedFieldFormat?: SerializedFieldFormat
) {
- if (!mapping) {
+ if (!serializedFieldFormat) {
return new DefaultFieldFormat();
}
- const { id } = mapping;
- if (id === 'range') {
- const RangeFormat = FieldFormat.from((range: any) => {
- const nestedFormatter = mapping.params as SerializedFieldFormat;
- const format = getFieldFormat(this, nestedFormatter.id, nestedFormatter.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;
+ const getFormat = (mapping: SerializedFieldFormat): IFieldFormat => {
+ const { id, params = {} } = mapping;
+ if (id) {
+ const Format = this.getType(id);
+
+ if (Format) {
+ return new Format(params, getConfig);
}
+ }
+
+ return new DefaultFieldFormat();
+ };
- return format.convert(val, type);
- };
+ // decorate getFormat to handle custom types created by aggs
+ const getFieldFormat = getFormatWithAggs(getFormat);
- return {
- convert,
- getConverterFor: (type: FieldFormatsContentType) => (val: string) => convert(val, type),
- } as IFieldFormat;
- } else {
- return getFieldFormat(this, id, mapping.params);
- }
+ return getFieldFormat(serializedFieldFormat);
};
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 1554ac71f8c55..984ce18aa4d83 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -168,7 +168,6 @@ import {
UrlFormat,
StringFormat,
TruncateFormat,
- serializeFieldFormat,
} from '../common/field_formats';
import { DateFormat } from './field_formats';
@@ -179,8 +178,6 @@ export const fieldFormats = {
FieldFormat,
FieldFormatsRegistry, // exported only for tests. Consider mock.
- serialize: serializeFieldFormat,
-
DEFAULT_CONVERTER_COLOR,
HTML_CONTEXT_TYPE,
TEXT_CONTEXT_TYPE,
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index 23213d4d1165a..31dc5b51a06f5 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -154,6 +154,7 @@ import { SearchParams } from 'elasticsearch';
import { SearchResponse as SearchResponse_2 } from 'elasticsearch';
import { SearchShardsParams } from 'elasticsearch';
import { SearchTemplateParams } from 'elasticsearch';
+import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/public';
import { SimpleSavedObject } from 'src/core/public';
import { SnapshotCreateParams } from 'elasticsearch';
import { SnapshotCreateRepositoryParams } from 'elasticsearch';
@@ -621,7 +622,6 @@ export type FieldFormatInstanceType = (new (params?: any, getConfig?: FieldForma
export const fieldFormats: {
FieldFormat: typeof FieldFormat;
FieldFormatsRegistry: typeof FieldFormatsRegistry;
- serialize: (agg: import("./search").AggConfig) => import("../../expressions").SerializedFieldFormat
);
}
-
-Agg.propTypes = {
- disableDelete: PropTypes.bool,
- fields: PropTypes.object,
- model: PropTypes.object,
- onAdd: PropTypes.func,
- onChange: PropTypes.func,
- onDelete: PropTypes.func,
- panel: PropTypes.object,
- series: PropTypes.object,
- siblings: PropTypes.array,
- uiRestrictions: PropTypes.object,
- dragHandleProps: PropTypes.object,
-};
diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_row.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_row.tsx
similarity index 86%
rename from src/plugins/vis_type_timeseries/public/application/components/aggs/agg_row.js
rename to src/plugins/vis_type_timeseries/public/application/components/aggs/agg_row.tsx
index a2f1640904dd0..0363ba486a775 100644
--- a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_row.js
+++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_row.tsx
@@ -17,15 +17,26 @@
* under the License.
*/
-import PropTypes from 'prop-types';
import React from 'react';
import { last } from 'lodash';
-import { AddDeleteButtons } from '../add_delete_buttons';
import { EuiIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
-import { SeriesDragHandler } from '../series_drag_handler';
import { i18n } from '@kbn/i18n';
+import { AddDeleteButtons } from '../add_delete_buttons';
+import { SeriesDragHandler } from '../series_drag_handler';
+import { MetricsItemsSchema } from '../../../../common/types';
+import { DragHandleProps } from '../../../types';
-export function AggRow(props) {
+interface AggRowProps {
+ disableDelete: boolean;
+ model: MetricsItemsSchema;
+ siblings: MetricsItemsSchema[];
+ dragHandleProps: DragHandleProps;
+ children: React.ReactNode;
+ onAdd: () => void;
+ onDelete: () => void;
+}
+
+export function AggRow(props: AggRowProps) {
let iconType = 'eyeClosed';
let iconColor = 'subdued';
const lastSibling = last(props.siblings);
@@ -71,12 +82,3 @@ export function AggRow(props) {
);
}
-
-AggRow.propTypes = {
- disableDelete: PropTypes.bool,
- model: PropTypes.object,
- onAdd: PropTypes.func,
- onDelete: PropTypes.func,
- siblings: PropTypes.array,
- dragHandleProps: PropTypes.object,
-};
diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.tsx
similarity index 88%
rename from src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.js
rename to src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.tsx
index 7ff6b6eb56692..6fa1a2adaa08e 100644
--- a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.js
+++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.tsx
@@ -17,14 +17,17 @@
* under the License.
*/
-import PropTypes from 'prop-types';
import React from 'react';
-import { EuiComboBox } from '@elastic/eui';
+import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { injectI18n } from '@kbn/i18n/react';
+// @ts-ignore
import { isMetricEnabled } from '../../lib/check_ui_restrictions';
+import { MetricsItemsSchema } from '../../../../common/types';
+import { TimeseriesUIRestrictions } from '../../../../common/ui_restrictions';
-const metricAggs = [
+type AggSelectOption = EuiComboBoxOptionOption;
+
+const metricAggs: AggSelectOption[] = [
{
label: i18n.translate('visTypeTimeseries.aggSelect.metricsAggs.averageLabel', {
defaultMessage: 'Average',
@@ -123,7 +126,7 @@ const metricAggs = [
},
];
-const pipelineAggs = [
+const pipelineAggs: AggSelectOption[] = [
{
label: i18n.translate('visTypeTimeseries.aggSelect.pipelineAggs.bucketScriptLabel', {
defaultMessage: 'Bucket Script',
@@ -162,7 +165,7 @@ const pipelineAggs = [
},
];
-const siblingAggs = [
+const siblingAggs: AggSelectOption[] = [
{
label: i18n.translate('visTypeTimeseries.aggSelect.siblingAggs.overallAverageLabel', {
defaultMessage: 'Overall Average',
@@ -207,7 +210,7 @@ const siblingAggs = [
},
];
-const specialAggs = [
+const specialAggs: AggSelectOption[] = [
{
label: i18n.translate('visTypeTimeseries.aggSelect.specialAggs.seriesAggLabel', {
defaultMessage: 'Series Agg',
@@ -224,14 +227,23 @@ const specialAggs = [
const allAggOptions = [...metricAggs, ...pipelineAggs, ...siblingAggs, ...specialAggs];
-function filterByPanelType(panelType) {
- return (agg) => {
+function filterByPanelType(panelType: string) {
+ return (agg: AggSelectOption) => {
if (panelType === 'table') return agg.value !== 'series_agg';
return true;
};
}
-function AggSelectUi(props) {
+interface AggSelectUiProps {
+ id: string;
+ panelType: string;
+ siblings: MetricsItemsSchema[];
+ value: string;
+ uiRestrictions?: TimeseriesUIRestrictions;
+ onChange: (currentlySelectedOptions: AggSelectOption[]) => void;
+}
+
+export function AggSelect(props: AggSelectUiProps) {
const { siblings, panelType, value, onChange, uiRestrictions, ...rest } = props;
const selectedOptions = allAggOptions.filter((option) => {
@@ -242,11 +254,11 @@ function AggSelectUi(props) {
if (siblings.length <= 1) enablePipelines = false;
- let options;
+ let options: EuiComboBoxOptionOption[];
if (panelType === 'metrics') {
options = metricAggs;
} else {
- const disableSiblingAggs = (agg) => ({
+ const disableSiblingAggs = (agg: AggSelectOption) => ({
...agg,
disabled: !enablePipelines || !isMetricEnabled(agg.value, uiRestrictions),
});
@@ -282,9 +294,9 @@ function AggSelectUi(props) {
];
}
- const handleChange = (selectedOptions) => {
- if (!selectedOptions || selectedOptions.length <= 0) return;
- onChange(selectedOptions);
+ const handleChange = (currentlySelectedOptions: AggSelectOption[]) => {
+ if (!currentlySelectedOptions || currentlySelectedOptions.length <= 0) return;
+ onChange(currentlySelectedOptions);
};
return (
@@ -303,13 +315,3 @@ function AggSelectUi(props) {