No data available
@@ -316,7 +203,7 @@ exports[`Inspector Data View component should render empty state 1`] = `
The element did not provide any data.
@@ -329,7 +216,7 @@ exports[`Inspector Data View component should render empty state 1`] = `
-
+
`;
exports[`Inspector Data View component should render loading state 1`] = `
@@ -442,6 +329,20 @@ exports[`Inspector Data View component should render loading state 1`] = `
}
}
>
+
loading
diff --git a/src/plugins/inspector/public/views/data/components/data_table.tsx b/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx
similarity index 56%
rename from src/plugins/inspector/public/views/data/components/data_table.tsx
rename to src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx
index 69be069272f79..f842568859fc2 100644
--- a/src/plugins/inspector/public/views/data/components/data_table.tsx
+++ b/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx
@@ -35,8 +35,10 @@ import { i18n } from '@kbn/i18n';
import { DataDownloadOptions } from './download_options';
import { DataViewRow, DataViewColumn } from '../types';
-import { TabularData } from '../../../../common/adapters/data/types';
import { IUiSettingsClient } from '../../../../../../core/public';
+import { Datatable, DatatableColumn } from '../../../../../expressions/public';
+import { FieldFormatsStart } from '../../../field_formats';
+import { TriggerId, UiActionsStart } from '../../../../../ui_actions/public';
interface DataTableFormatState {
columns: DataViewColumn[];
@@ -44,10 +46,21 @@ interface DataTableFormatState {
}
interface DataTableFormatProps {
- data: TabularData;
+ data: Datatable;
exportTitle: string;
uiSettings: IUiSettingsClient;
- isFormatted?: boolean;
+ fieldFormats: FieldFormatsStart;
+ uiActions: UiActionsStart;
+ isFilterable: (column: DatatableColumn) => boolean;
+}
+
+interface RenderCellArguments {
+ table: Datatable;
+ columnIndex: number;
+ rowIndex: number;
+ formattedValue: string;
+ uiActions: UiActionsStart;
+ isFilterable: boolean;
}
export class DataTableFormat extends Component {
@@ -55,25 +68,35 @@ export class DataTableFormat extends Component
- {isFormatted ? value.formatted : value}
+ {formattedValue}
- {dataColumn.filter && (
+ {isFilterable && (
}
@@ -81,23 +104,29 @@ export class DataTableFormat extends Component dataColumn.filter(value)}
+ onClick={() => {
+ const value = table.rows[rowIndex][column.id];
+ const eventData = { table, column: columnIndex, row: rowIndex, value };
+ uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER' as TriggerId, {
+ data: { data: [eventData] },
+ });
+ }}
/>
)}
- {dataColumn.filterOut && (
+ {isFilterable && (
}
@@ -105,12 +134,21 @@ export class DataTableFormat extends Component dataColumn.filterOut(value)}
+ onClick={() => {
+ const value = table.rows[rowIndex][column.id];
+ const eventData = { table, column: columnIndex, row: rowIndex, value };
+ uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER' as TriggerId, {
+ data: { data: [eventData], negate: true },
+ });
+ }}
/>
@@ -121,7 +159,12 @@ export class DataTableFormat extends Component ({
- name: dataColumn.name,
- field: dataColumn.field,
- sortable: isFormatted ? (row: DataViewRow) => row[dataColumn.field].raw : true,
- render: (value: any) => DataTableFormat.renderCell(dataColumn, value, isFormatted),
- }));
+ const columns = data.columns.map((dataColumn: any, index: number) => {
+ const formatParams = { id: 'string', ...dataColumn.meta.params };
+ const fieldFormatter = fieldFormats.deserialize(formatParams);
+ const filterable = isFilterable(dataColumn);
+ return {
+ originalColumn: () => dataColumn,
+ name: dataColumn.name,
+ field: dataColumn.id,
+ sortable: true,
+ render: (value: any) => {
+ const formattedValue = fieldFormatter.convert(value);
+ const rowIndex = data.rows.findIndex((row) => row[dataColumn.id] === value) || 0;
+
+ return DataTableFormat.renderCell({
+ table: data,
+ columnIndex: index,
+ rowIndex,
+ formattedValue,
+ uiActions,
+ isFilterable: filterable,
+ });
+ },
+ };
+ });
return { columns, rows: data.rows };
}
@@ -152,12 +213,12 @@ export class DataTableFormat extends Component
diff --git a/src/plugins/inspector/public/views/data/components/data_view.test.tsx b/src/plugins/data/public/utils/table_inspector_view/components/data_view.test.tsx
similarity index 77%
rename from src/plugins/inspector/public/views/data/components/data_view.test.tsx
rename to src/plugins/data/public/utils/table_inspector_view/components/data_view.test.tsx
index 82bec5ee3fe8c..975a91548d799 100644
--- a/src/plugins/inspector/public/views/data/components/data_view.test.tsx
+++ b/src/plugins/data/public/utils/table_inspector_view/components/data_view.test.tsx
@@ -18,11 +18,11 @@
*/
import React, { Suspense } from 'react';
-import { getDataViewDescription } from '../index';
-import { DataAdapter } from '../../../../common/adapters/data';
+import { getTableViewDescription } from '../index';
import { mountWithIntl } from '@kbn/test/jest';
+import { TablesAdapter } from '../../../../../expressions/common';
-jest.mock('../lib/export_csv', () => ({
+jest.mock('./export_csv', () => ({
exportAsCsv: jest.fn(),
}));
@@ -30,13 +30,18 @@ describe('Inspector Data View', () => {
let DataView: any;
beforeEach(() => {
- DataView = getDataViewDescription();
+ DataView = getTableViewDescription(() => ({
+ uiActions: {} as any,
+ uiSettings: {} as any,
+ fieldFormats: {} as any,
+ isFilterable: jest.fn(),
+ }));
});
it('should only show if data adapter is present', () => {
- const adapter = new DataAdapter();
+ const adapter = new TablesAdapter();
- expect(DataView.shouldShow({ data: adapter })).toBe(true);
+ expect(DataView.shouldShow({ tables: adapter })).toBe(true);
expect(DataView.shouldShow({})).toBe(false);
});
@@ -44,7 +49,7 @@ describe('Inspector Data View', () => {
let adapters: any;
beforeEach(() => {
- adapters = { data: new DataAdapter() };
+ adapters = { tables: new TablesAdapter() };
});
it('should render loading state', () => {
@@ -60,9 +65,7 @@ describe('Inspector Data View', () => {
it('should render empty state', async () => {
const component = mountWithIntl(); // eslint-disable-line react/jsx-pascal-case
- const tabularLoader = Promise.resolve(null);
- adapters.data.setTabularLoader(() => tabularLoader);
- await tabularLoader;
+ adapters.tables.logDatatable({ columns: [{ id: '1' }], rows: [{ '1': 123 }] });
// After the loader has resolved we'll still need one update, to "flush" the state changes
component.update();
expect(component).toMatchSnapshot();
diff --git a/src/plugins/data/public/utils/table_inspector_view/components/data_view.tsx b/src/plugins/data/public/utils/table_inspector_view/components/data_view.tsx
new file mode 100644
index 0000000000000..97dca45d742c9
--- /dev/null
+++ b/src/plugins/data/public/utils/table_inspector_view/components/data_view.tsx
@@ -0,0 +1,137 @@
+/*
+ * 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 React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiEmptyPrompt } from '@elastic/eui';
+
+import { DataTableFormat } from './data_table';
+import { IUiSettingsClient } from '../../../../../../core/public';
+import { InspectorViewProps, Adapters } from '../../../../../inspector/public';
+import { UiActionsStart } from '../../../../../ui_actions/public';
+import { FieldFormatsStart } from '../../../field_formats';
+import { TablesAdapter, Datatable, DatatableColumn } from '../../../../../expressions/public';
+
+interface DataViewComponentState {
+ datatable: Datatable;
+ adapters: Adapters;
+}
+
+interface DataViewComponentProps extends InspectorViewProps {
+ uiSettings: IUiSettingsClient;
+ uiActions: UiActionsStart;
+ fieldFormats: FieldFormatsStart;
+ isFilterable: (column: DatatableColumn) => boolean;
+}
+
+class DataViewComponent extends Component {
+ static propTypes = {
+ adapters: PropTypes.object.isRequired,
+ title: PropTypes.string.isRequired,
+ uiSettings: PropTypes.object,
+ uiActions: PropTypes.object.isRequired,
+ fieldFormats: PropTypes.object.isRequired,
+ isFilterable: PropTypes.func.isRequired,
+ };
+
+ state = {} as DataViewComponentState;
+
+ static getDerivedStateFromProps(
+ nextProps: Readonly,
+ state: DataViewComponentState
+ ) {
+ if (state && nextProps.adapters === state.adapters) {
+ return null;
+ }
+
+ const { tables } = nextProps.adapters.tables;
+ const keys = Object.keys(tables);
+ const datatable = keys.length ? tables[keys[0]] : undefined;
+
+ return {
+ adapters: nextProps.adapters,
+ datatable,
+ };
+ }
+
+ onUpdateData = (tables: TablesAdapter['tables']) => {
+ const keys = Object.keys(tables);
+ const datatable = keys.length ? tables[keys[0]] : undefined;
+
+ if (datatable) {
+ this.setState({
+ datatable,
+ });
+ }
+ };
+
+ componentDidMount() {
+ this.props.adapters.tables!.on('change', this.onUpdateData);
+ }
+
+ componentWillUnmount() {
+ this.props.adapters.tables!.removeListener('change', this.onUpdateData);
+ }
+
+ static renderNoData() {
+ return (
+
+
+
+ }
+ body={
+
+
+
+
+
+ }
+ />
+ );
+ }
+
+ render() {
+ if (!this.state.datatable) {
+ return DataViewComponent.renderNoData();
+ }
+
+ return (
+
+ );
+ }
+}
+
+// default export required for React.Lazy
+// eslint-disable-next-line import/no-default-export
+export default DataViewComponent;
diff --git a/src/plugins/data/public/utils/table_inspector_view/components/data_view_wrapper.tsx b/src/plugins/data/public/utils/table_inspector_view/components/data_view_wrapper.tsx
new file mode 100644
index 0000000000000..d8b96da36628c
--- /dev/null
+++ b/src/plugins/data/public/utils/table_inspector_view/components/data_view_wrapper.tsx
@@ -0,0 +1,47 @@
+/*
+ * 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 React, { lazy } from 'react';
+import { IUiSettingsClient } from 'kibana/public';
+import { UiActionsStart } from '../../../../../ui_actions/public';
+import { FieldFormatsStart } from '../../../field_formats';
+import { DatatableColumn } from '../../../../../expressions/common/expression_types/specs';
+
+const DataViewComponent = lazy(() => import('./data_view'));
+
+export const getDataViewComponentWrapper = (
+ getStartServices: () => {
+ uiActions: UiActionsStart;
+ fieldFormats: FieldFormatsStart;
+ uiSettings: IUiSettingsClient;
+ isFilterable: (column: DatatableColumn) => boolean;
+ }
+) => {
+ return (props: any) => {
+ return (
+
+ );
+ };
+};
diff --git a/src/plugins/inspector/public/views/data/components/download_options.tsx b/src/plugins/data/public/utils/table_inspector_view/components/download_options.tsx
similarity index 77%
rename from src/plugins/inspector/public/views/data/components/download_options.tsx
rename to src/plugins/data/public/utils/table_inspector_view/components/download_options.tsx
index cedb723091638..f849f598e9c69 100644
--- a/src/plugins/inspector/public/views/data/components/download_options.tsx
+++ b/src/plugins/data/public/utils/table_inspector_view/components/download_options.tsx
@@ -24,8 +24,8 @@ import { i18n } from '@kbn/i18n';
import { EuiButton, EuiContextMenuItem, EuiContextMenuPanel, EuiPopover } from '@elastic/eui';
import { DataViewColumn, DataViewRow } from '../types';
-
-import { exportAsCsv } from '../lib/export_csv';
+import { exportAsCsv } from './export_csv';
+import { FieldFormatsStart } from '../../../field_formats';
interface DataDownloadOptionsState {
isPopoverOpen: boolean;
@@ -38,6 +38,7 @@ interface DataDownloadOptionsProps {
csvSeparator: string;
quoteValues: boolean;
isFormatted?: boolean;
+ fieldFormats: FieldFormatsStart;
}
class DataDownloadOptions extends Component {
@@ -45,9 +46,9 @@ class DataDownloadOptions extends Component {
+ exportCsv = (isFormatted: boolean = true) => {
let filename = this.props.title;
if (!filename || filename.length === 0) {
- filename = i18n.translate('inspector.data.downloadOptionsUnsavedFilename', {
+ filename = i18n.translate('data.inspector.table.downloadOptionsUnsavedFilename', {
defaultMessage: 'unsaved',
});
}
@@ -79,38 +80,24 @@ class DataDownloadOptions extends Component {
- this.exportCsv({
- valueFormatter: (item: any) => item.formatted,
- });
+ this.exportCsv(true);
};
exportFormattedAsRawCsv = () => {
- this.exportCsv({
- valueFormatter: (item: any) => item.raw,
- });
+ this.exportCsv(false);
};
- renderUnformattedDownload() {
- return (
-
-
-
- );
- }
-
renderFormattedDownloads() {
const button = (
@@ -121,14 +108,14 @@ class DataDownloadOptions extends Component
}
toolTipPosition="left"
>
,
@@ -137,13 +124,13 @@ class DataDownloadOptions extends Component
}
toolTipPosition="left"
>
-
+
,
];
@@ -162,9 +149,7 @@ class DataDownloadOptions extends Component escape(col.name, quoteValues));
+ const formatters = columns.map((column) => {
+ return fieldFormats.deserialize(column.originalColumn().meta.params);
+ });
+
// Convert the array of row objects to an array of row arrays
- const orderedFieldNames = columns.map((col) => col.field);
const csvRows = rows.map((row) => {
- return orderedFieldNames.map((field) =>
- escape(valueFormatter ? valueFormatter(row[field]) : row[field], quoteValues)
- );
+ return columns.map((column, i) => {
+ return escape(
+ isFormatted ? formatters[i].convert(row[column.field]) : row[column.field],
+ quoteValues
+ );
+ });
});
return (
@@ -69,14 +77,18 @@ export function exportAsCsv({
filename,
columns,
rows,
- valueFormatter,
+ isFormatted,
csvSeparator,
quoteValues,
+ fieldFormats,
}: any) {
const type = 'text/plain;charset=utf-8';
- const csv = new Blob([buildCsv(columns, rows, csvSeparator, quoteValues, valueFormatter)], {
- type,
- });
+ const csv = new Blob(
+ [buildCsv(columns, rows, csvSeparator, quoteValues, isFormatted, fieldFormats)],
+ {
+ type,
+ }
+ );
saveAs(csv, filename);
}
diff --git a/src/plugins/data/public/utils/table_inspector_view/index.ts b/src/plugins/data/public/utils/table_inspector_view/index.ts
new file mode 100644
index 0000000000000..3769298af05f3
--- /dev/null
+++ b/src/plugins/data/public/utils/table_inspector_view/index.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+import { IUiSettingsClient } from 'kibana/public';
+import { Adapters, InspectorViewDescription } from '../../../../inspector/public';
+import { getDataViewComponentWrapper } from './components/data_view_wrapper';
+import { UiActionsStart } from '../../../../ui_actions/public';
+import { FieldFormatsStart } from '../../field_formats';
+import { DatatableColumn } from '../../../../expressions/common/expression_types/specs';
+
+export const getTableViewDescription = (
+ getStartServices: () => {
+ uiActions: UiActionsStart;
+ fieldFormats: FieldFormatsStart;
+ isFilterable: (column: DatatableColumn) => boolean;
+ uiSettings: IUiSettingsClient;
+ }
+): InspectorViewDescription => ({
+ title: i18n.translate('data.inspector.table.dataTitle', {
+ defaultMessage: 'Data',
+ }),
+ order: 10,
+ help: i18n.translate('data.inspector.table..dataDescriptionTooltip', {
+ defaultMessage: 'View the data behind the visualization',
+ }),
+ shouldShow(adapters: Adapters) {
+ return Boolean(adapters.tables);
+ },
+ component: getDataViewComponentWrapper(getStartServices),
+});
diff --git a/src/plugins/inspector/public/views/data/types.ts b/src/plugins/data/public/utils/table_inspector_view/types.ts
similarity index 70%
rename from src/plugins/inspector/public/views/data/types.ts
rename to src/plugins/data/public/utils/table_inspector_view/types.ts
index 31de9eb3a152e..dc85c3c2e3135 100644
--- a/src/plugins/inspector/public/views/data/types.ts
+++ b/src/plugins/data/public/utils/table_inspector_view/types.ts
@@ -17,15 +17,20 @@
* under the License.
*/
-import { TabularDataRow } from '../../../common/adapters';
+import { Datatable, DatatableColumn, DatatableRow } from '../../../../expressions/common';
-type DataViewColumnRender = (value: string, _item: TabularDataRow) => string;
+type DataViewColumnRender = (value: string, _item: DatatableRow) => string;
export interface DataViewColumn {
+ originalColumn: () => DatatableColumn;
name: string;
field: string;
- sortable: (item: TabularDataRow) => string | number;
+ sortable: (item: DatatableRow) => string | number;
render: DataViewColumnRender;
}
-export type DataViewRow = TabularDataRow;
+export type DataViewRow = DatatableRow;
+
+export interface TableInspectorAdapter {
+ [key: string]: Datatable;
+}
diff --git a/src/plugins/data/server/index_patterns/index_patterns_api_client.ts b/src/plugins/data/server/index_patterns/index_patterns_api_client.ts
index 21a3bf6e73e61..9023044184df3 100644
--- a/src/plugins/data/server/index_patterns/index_patterns_api_client.ts
+++ b/src/plugins/data/server/index_patterns/index_patterns_api_client.ts
@@ -30,8 +30,14 @@ export class IndexPatternsApiServer implements IIndexPatternsApiClient {
constructor(elasticsearchClient: ElasticsearchClient) {
this.esClient = elasticsearchClient;
}
- async getFieldsForWildcard({ pattern, metaFields, type, rollupIndex }: GetFieldsOptions) {
- const indexPatterns = new IndexPatternsFetcher(this.esClient);
+ async getFieldsForWildcard({
+ pattern,
+ metaFields,
+ type,
+ rollupIndex,
+ allowNoIndex,
+ }: GetFieldsOptions) {
+ const indexPatterns = new IndexPatternsFetcher(this.esClient, allowNoIndex);
return await indexPatterns.getFieldsForWildcard({
pattern,
metaFields,
diff --git a/src/plugins/data/server/index_patterns/routes.ts b/src/plugins/data/server/index_patterns/routes.ts
index e9dbc2e972c68..f0b51e456337f 100644
--- a/src/plugins/data/server/index_patterns/routes.ts
+++ b/src/plugins/data/server/index_patterns/routes.ts
@@ -75,13 +75,20 @@ export function registerRoutes(
}),
type: schema.maybe(schema.string()),
rollup_index: schema.maybe(schema.string()),
+ allow_no_index: schema.maybe(schema.boolean()),
}),
},
},
async (context, request, response) => {
const { asCurrentUser } = context.core.elasticsearch.client;
const indexPatterns = new IndexPatternsFetcher(asCurrentUser);
- const { pattern, meta_fields: metaFields, type, rollup_index: rollupIndex } = request.query;
+ const {
+ pattern,
+ meta_fields: metaFields,
+ type,
+ rollup_index: rollupIndex,
+ allow_no_index: allowNoIndex,
+ } = request.query;
let parsedFields: string[] = [];
try {
@@ -96,6 +103,9 @@ export function registerRoutes(
metaFields: parsedFields,
type,
rollupIndex,
+ fieldCapsOptions: {
+ allow_no_indices: allowNoIndex || false,
+ },
});
return response.ok({
diff --git a/src/plugins/data/server/index_patterns/routes/create_index_pattern.ts b/src/plugins/data/server/index_patterns/routes/create_index_pattern.ts
index 57a745b19748d..1163fd2dc9953 100644
--- a/src/plugins/data/server/index_patterns/routes/create_index_pattern.ts
+++ b/src/plugins/data/server/index_patterns/routes/create_index_pattern.ts
@@ -50,6 +50,7 @@ const indexPatternSpecSchema = schema.object({
})
)
),
+ allowNoIndex: schema.maybe(schema.boolean()),
});
export const registerCreateIndexPatternRoute = (
diff --git a/src/plugins/data/server/index_patterns/routes/update_index_pattern.ts b/src/plugins/data/server/index_patterns/routes/update_index_pattern.ts
index 10567544af6ea..8bd59e47730fd 100644
--- a/src/plugins/data/server/index_patterns/routes/update_index_pattern.ts
+++ b/src/plugins/data/server/index_patterns/routes/update_index_pattern.ts
@@ -38,6 +38,7 @@ const indexPatternUpdateSchema = schema.object({
),
fieldFormats: schema.maybe(schema.recordOf(schema.string(), serializedFieldFormatSchema)),
fields: schema.maybe(schema.recordOf(schema.string(), fieldSpecSchema)),
+ allowNoIndex: schema.maybe(schema.boolean()),
});
export const registerUpdateIndexPatternRoute = (
diff --git a/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts b/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts
index b1410e2498667..3b223e6fdb9b2 100644
--- a/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts
+++ b/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts
@@ -94,4 +94,55 @@ Object {
expect(migrationFn(input, savedObjectMigrationContext)).toEqual(expected);
});
});
+
+ describe('7.11.0', () => {
+ const migrationFn = indexPatternSavedObjectTypeMigrations['7.11.0'];
+
+ test('should set allowNoIndex', () => {
+ const input = {
+ type: 'index-pattern',
+ id: 'logs-*',
+ attributes: {},
+ };
+ const expected = {
+ type: 'index-pattern',
+ id: 'logs-*',
+ attributes: {
+ allowNoIndex: true,
+ },
+ };
+
+ expect(migrationFn(input, savedObjectMigrationContext)).toEqual(expected);
+
+ const input2 = {
+ type: 'index-pattern',
+ id: 'metrics-*',
+ attributes: {},
+ };
+ const expected2 = {
+ type: 'index-pattern',
+ id: 'metrics-*',
+ attributes: {
+ allowNoIndex: true,
+ },
+ };
+
+ expect(migrationFn(input2, savedObjectMigrationContext)).toEqual(expected2);
+
+ const input3 = {
+ type: 'index-pattern',
+ id: 'xxx',
+ attributes: {},
+ };
+ const expected3 = {
+ type: 'index-pattern',
+ id: 'xxx',
+ attributes: {
+ allowNoIndex: undefined,
+ },
+ };
+
+ expect(migrationFn(input3, savedObjectMigrationContext)).toEqual(expected3);
+ });
+ });
});
diff --git a/src/plugins/data/server/saved_objects/index_pattern_migrations.ts b/src/plugins/data/server/saved_objects/index_pattern_migrations.ts
index 768041a376ad1..4650aeefba056 100644
--- a/src/plugins/data/server/saved_objects/index_pattern_migrations.ts
+++ b/src/plugins/data/server/saved_objects/index_pattern_migrations.ts
@@ -54,7 +54,16 @@ const migrateSubTypeAndParentFieldProperties: SavedObjectMigrationFn =
};
};
+const addAllowNoIndex: SavedObjectMigrationFn = (doc) => ({
+ ...doc,
+ attributes: {
+ ...doc.attributes,
+ allowNoIndex: doc.id === 'logs-*' || doc.id === 'metrics-*' || undefined,
+ },
+});
+
export const indexPatternSavedObjectTypeMigrations = {
'6.5.0': flow(migrateAttributeTypeAndAttributeTypeMeta),
'7.6.0': flow(migrateSubTypeAndParentFieldProperties),
+ '7.11.0': flow(addAllowNoIndex),
};
diff --git a/src/plugins/data/server/search/aggs/aggs_service.ts b/src/plugins/data/server/search/aggs/aggs_service.ts
index c23f748b1eeb5..ae1cf3054ec3f 100644
--- a/src/plugins/data/server/search/aggs/aggs_service.ts
+++ b/src/plugins/data/server/search/aggs/aggs_service.ts
@@ -86,6 +86,7 @@ export class AggsService {
const {
calculateAutoTimeExpression,
getDateMetaByDatatableColumn,
+ datatableUtilities,
types,
} = this.aggsCommonService.start({
getConfig,
@@ -130,7 +131,8 @@ export class AggsService {
return {
calculateAutoTimeExpression,
getDateMetaByDatatableColumn,
- createAggConfigs: (indexPattern, configStates = [], schemas) => {
+ datatableUtilities,
+ createAggConfigs: (indexPattern, configStates = []) => {
return new AggConfigs(indexPattern, configStates, { typesRegistry });
},
types: typesRegistry,
diff --git a/src/plugins/data/server/search/aggs/mocks.ts b/src/plugins/data/server/search/aggs/mocks.ts
index 7b7f3d3c40652..66a6aa2c7d803 100644
--- a/src/plugins/data/server/search/aggs/mocks.ts
+++ b/src/plugins/data/server/search/aggs/mocks.ts
@@ -70,6 +70,11 @@ export const searchAggsSetupMock = (): AggsSetup => ({
const commonStartMock = (): AggsCommonStart => ({
calculateAutoTimeExpression: getCalculateAutoTimeExpression(getConfig),
getDateMetaByDatatableColumn: jest.fn(),
+ datatableUtilities: {
+ getIndexPattern: jest.fn(),
+ getAggConfig: jest.fn(),
+ isFilterable: jest.fn(),
+ },
createAggConfigs: jest.fn().mockImplementation((indexPattern, configStates = [], schemas) => {
return new AggConfigs(indexPattern, configStates, {
typesRegistry: mockAggTypesRegistry(),
diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts
index 620df9c8edcb0..983e4a44370d9 100644
--- a/src/plugins/data/server/search/es_search/es_search_strategy.ts
+++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts
@@ -25,6 +25,7 @@ import type { SearchUsage } from '../collectors';
import { getDefaultSearchParams, getShardTimeout, shimAbortSignal } from './request_utils';
import { toKibanaSearchResponse } from './response_utils';
import { searchUsageObserver } from '../collectors/usage';
+import { KbnServerError } from '../../../../kibana_utils/server';
export const esSearchStrategyProvider = (
config$: Observable,
@@ -35,7 +36,7 @@ export const esSearchStrategyProvider = (
// Only default index pattern type is supported here.
// See data_enhanced for other type support.
if (request.indexType) {
- throw new Error(`Unsupported index pattern type ${request.indexType}`);
+ throw new KbnServerError(`Unsupported index pattern type ${request.indexType}`, 400);
}
const search = async () => {
diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts
index 7b44aa18bf8fc..ae6362fac1b21 100644
--- a/src/plugins/data/server/search/routes/msearch.ts
+++ b/src/plugins/data/server/search/routes/msearch.ts
@@ -23,6 +23,7 @@ import { IRouter } from 'src/core/server';
import { SearchRouteDependencies } from '../search_service';
import { getCallMsearch } from './call_msearch';
+import { reportServerError } from '../../../../kibana_utils/server';
/**
* The msearch route takes in an array of searches, each consisting of header
@@ -69,15 +70,7 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc
const response = await callMsearch({ body: request.body });
return res.ok(response);
} catch (err) {
- return res.customError({
- statusCode: err.statusCode || 500,
- body: {
- message: err.message,
- attributes: {
- error: err.body?.error || err.message,
- },
- },
- });
+ return reportServerError(res, err);
}
}
);
diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts
index ed519164c8e43..6c27b7e2c43d3 100644
--- a/src/plugins/data/server/search/routes/search.ts
+++ b/src/plugins/data/server/search/routes/search.ts
@@ -22,6 +22,7 @@ import { schema } from '@kbn/config-schema';
import type { IRouter } from 'src/core/server';
import { getRequestAbortedSignal } from '../../lib';
import { shimHitsTotal } from './shim_hits_total';
+import { reportServerError } from '../../../../kibana_utils/server';
export function registerSearchRoute(router: IRouter): void {
router.post(
@@ -74,15 +75,7 @@ export function registerSearchRoute(router: IRouter): void {
},
});
} catch (err) {
- return res.customError({
- statusCode: err.statusCode || 500,
- body: {
- message: err.message,
- attributes: {
- error: err.body?.error || err.message,
- },
- },
- });
+ return reportServerError(res, err);
}
}
);
@@ -106,15 +99,7 @@ export function registerSearchRoute(router: IRouter): void {
await context.search!.cancel(id, { strategy });
return res.ok();
} catch (err) {
- return res.customError({
- statusCode: err.statusCode,
- body: {
- message: err.message,
- attributes: {
- error: err.body.error,
- },
- },
- });
+ return reportServerError(res, err);
}
}
);
diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts
index 6c8683220bc4c..5de019cd1b83e 100644
--- a/src/plugins/data/server/search/search_service.ts
+++ b/src/plugins/data/server/search/search_service.ts
@@ -73,6 +73,7 @@ import {
import { aggShardDelay } from '../../common/search/aggs/buckets/shard_delay_fn';
import { ConfigSchema } from '../../config';
import { SessionService, IScopedSessionService, ISessionService } from './session';
+import { KbnServerError } from '../../../kibana_utils/server';
declare module 'src/core/server' {
interface RequestHandlerContext {
@@ -305,7 +306,13 @@ export class SearchService implements Plugin {
private cancel = (id: string, options: ISearchOptions, deps: SearchStrategyDependencies) => {
const strategy = this.getSearchStrategy(options.strategy);
- return strategy.cancel ? strategy.cancel(id, options, deps) : Promise.resolve();
+ if (!strategy.cancel) {
+ throw new KbnServerError(
+ `Search strategy ${options.strategy} doesn't support cancellations`,
+ 400
+ );
+ }
+ return strategy.cancel(id, options, deps);
};
private getSearchStrategy = <
@@ -317,7 +324,7 @@ export class SearchService implements Plugin {
this.logger.debug(`Get strategy ${name}`);
const strategy = this.searchStrategies[name];
if (!strategy) {
- throw new Error(`Search strategy ${name} not found`);
+ throw new KbnServerError(`Search strategy ${name} not found`, 404);
}
return strategy;
};
diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md
index 4d24e6d1afd49..cd3527d5ad7ab 100644
--- a/src/plugins/data/server/server.api.md
+++ b/src/plugins/data/server/server.api.md
@@ -689,6 +689,7 @@ export class IndexPattern implements IIndexPattern {
// Warning: (ae-forgotten-export) The symbol "IndexPatternDeps" needs to be exported by the entry point index.d.ts
constructor({ spec, fieldFormats, shortDotsEnable, metaFields, }: IndexPatternDeps);
addScriptedField(name: string, script: string, fieldType?: string): Promise;
+ readonly allowNoIndex: boolean;
// (undocumented)
readonly deleteFieldFormat: (fieldName: string) => void;
// Warning: (ae-forgotten-export) The symbol "FieldAttrs" needs to be exported by the entry point index.d.ts
@@ -731,6 +732,7 @@ export class IndexPattern implements IIndexPattern {
fieldFormatMap: string | undefined;
type: string | undefined;
typeMeta: string | undefined;
+ allowNoIndex: true | undefined;
};
// (undocumented)
getComputedFields(): {
@@ -819,6 +821,7 @@ export class IndexPattern implements IIndexPattern {
//
// @public (undocumented)
export interface IndexPatternAttributes {
+ allowNoIndex?: boolean;
// (undocumented)
fieldAttrs?: string;
// (undocumented)
@@ -1115,7 +1118,7 @@ export class Plugin implements Plugin_2 void;
search: ISearchSetup;
fieldFormats: {
- register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number;
+ register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number;
};
};
// (undocumented)
@@ -1124,7 +1127,7 @@ export class Plugin implements Plugin_2 Promise;
};
indexPatterns: {
- indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise;
+ indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise;
};
search: ISearchStart>;
};
@@ -1388,7 +1391,7 @@ export function usageProvider(core: CoreSetup_2): SearchUsage;
// src/plugins/data/common/es_query/filters/meta_filter.ts:54:3 - (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:58:45 - (ae-forgotten-export) The symbol "IndexPatternFieldMap" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:64:5 - (ae-forgotten-export) The symbol "FormatFieldFn" needs to be exported by the entry point index.d.ts
-// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:128:7 - (ae-forgotten-export) The symbol "FieldAttrSet" needs to be exported by the entry point index.d.ts
+// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:133:7 - (ae-forgotten-export) The symbol "FieldAttrSet" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:40:23 - (ae-forgotten-export) The symbol "buildCustomFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:40:23 - (ae-forgotten-export) The symbol "buildFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:57:23 - (ae-forgotten-export) The symbol "datatableToCSV" needs to be exported by the entry point index.d.ts
diff --git a/src/plugins/discover/public/application/angular/directives/histogram.tsx b/src/plugins/discover/public/application/angular/directives/histogram.tsx
index 4c39c8bb25542..5a0bd5cca6109 100644
--- a/src/plugins/discover/public/application/angular/directives/histogram.tsx
+++ b/src/plugins/discover/public/application/angular/directives/histogram.tsx
@@ -17,25 +17,17 @@
* under the License.
*/
-import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui';
-import moment from 'moment-timezone';
-import { unitOfTime } from 'moment';
+import moment, { unitOfTime } from 'moment-timezone';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import lightEuiTheme from '@elastic/eui/dist/eui_theme_light.json';
-import darkEuiTheme from '@elastic/eui/dist/eui_theme_dark.json';
import {
- AnnotationDomainTypes,
Axis,
Chart,
HistogramBarSeries,
- LineAnnotation,
Position,
ScaleType,
Settings,
- RectAnnotation,
- TooltipValue,
TooltipType,
ElementClickListener,
XYChartElementEvent,
@@ -43,12 +35,17 @@ import {
Theme,
} from '@elastic/charts';
-import { i18n } from '@kbn/i18n';
import { IUiSettingsClient } from 'kibana/public';
import { EuiChartThemeType } from '@elastic/eui/dist/eui_charts_theme';
import { Subscription, combineLatest } from 'rxjs';
import { getServices } from '../../../kibana_services';
import { Chart as IChart } from '../helpers/point_series';
+import {
+ CurrentTime,
+ Endzones,
+ getAdjustedInterval,
+ renderEndzoneTooltip,
+} from '../../../../../charts/public';
export interface DiscoverHistogramProps {
chartData: IChart;
@@ -60,34 +57,6 @@ interface DiscoverHistogramState {
chartsBaseTheme: Theme;
}
-function findIntervalFromDuration(
- dateValue: number,
- esValue: number,
- esUnit: unitOfTime.Base,
- timeZone: string
-) {
- const date = moment.tz(dateValue, timeZone);
- const startOfDate = moment.tz(date, timeZone).startOf(esUnit);
- const endOfDate = moment.tz(date, timeZone).startOf(esUnit).add(esValue, esUnit);
- return endOfDate.valueOf() - startOfDate.valueOf();
-}
-
-function getIntervalInMs(
- value: number,
- esValue: number,
- esUnit: unitOfTime.Base,
- timeZone: string
-): number {
- switch (esUnit) {
- case 's':
- return 1000 * esValue;
- case 'ms':
- return 1 * esValue;
- default:
- return findIntervalFromDuration(value, esValue, esUnit, timeZone);
- }
-}
-
function getTimezone(uiSettings: IUiSettingsClient) {
if (uiSettings.isDefault('dateFormat:tz')) {
const detectedTimezone = moment.tz.guess();
@@ -98,27 +67,6 @@ function getTimezone(uiSettings: IUiSettingsClient) {
}
}
-export function findMinInterval(
- xValues: number[],
- esValue: number,
- esUnit: string,
- timeZone: string
-): number {
- return xValues.reduce((minInterval, currentXvalue, index) => {
- let currentDiff = minInterval;
- if (index > 0) {
- currentDiff = Math.abs(xValues[index - 1] - currentXvalue);
- }
- const singleUnitInterval = getIntervalInMs(
- currentXvalue,
- esValue,
- esUnit as unitOfTime.Base,
- timeZone
- );
- return Math.min(minInterval, singleUnitInterval, currentDiff);
- }, Number.MAX_SAFE_INTEGER);
-}
-
export class DiscoverHistogram extends Component {
public static propTypes = {
chartData: PropTypes.object,
@@ -132,10 +80,10 @@ export class DiscoverHistogram extends Component
+ getServices().theme.chartsBaseTheme$,
+ ]).subscribe(([chartsTheme, chartsBaseTheme]) =>
this.setState({ chartsTheme, chartsBaseTheme })
);
}
@@ -171,40 +119,6 @@ export class DiscoverHistogram extends Component (
- headerData: TooltipValue
- ): JSX.Element | string => {
- const headerDataValue = headerData.value;
- const formattedValue = this.formatXValue(headerDataValue);
-
- const partialDataText = i18n.translate('discover.histogram.partialData.bucketTooltipText', {
- defaultMessage:
- 'The selected time range does not include this entire bucket, it may contain partial data.',
- });
-
- if (headerDataValue < domainStart || headerDataValue + xInterval > domainEnd) {
- return (
-
-
-
-
-
- {partialDataText}
-
-
- {formattedValue}
-
- );
- }
-
- return formattedValue;
- };
-
public render() {
const uiSettings = getServices().uiSettings;
const timeZone = getTimezone(uiSettings);
@@ -216,8 +130,9 @@ export class DiscoverHistogram extends Component domainStart ? domainStart : data[0]?.x;
- const domainMax = domainEnd - xInterval > lastXValue ? domainEnd - xInterval : lastXValue;
+ const domainMin = Math.min(data[0]?.x, domainStart);
+ const domainMax = Math.max(domainEnd - xInterval, lastXValue);
const xDomain = {
min: domainMin,
max: domainMax,
- minInterval: findMinInterval(xValues, intervalESValue, intervalESUnit, timeZone),
- };
-
- // Domain end of 'now' will be milliseconds behind current time, so we extend time by 1 minute and check if
- // the annotation is within this range; if so, the line annotation uses the domainEnd as its value
- const now = moment();
- const isAnnotationAtEdge = moment(domainEnd).add(60000).isAfter(now) && now.isAfter(domainEnd);
- const lineAnnotationValue = isAnnotationAtEdge ? domainEnd : now;
-
- const lineAnnotationData = [
- {
- dataValue: lineAnnotationValue,
- },
- ];
- const isDarkMode = uiSettings.get('theme:darkMode');
-
- const lineAnnotationStyle = {
- line: {
- strokeWidth: 2,
- stroke: isDarkMode ? darkEuiTheme.euiColorDanger : lightEuiTheme.euiColorDanger,
- opacity: 0.7,
- },
+ minInterval: getAdjustedInterval(
+ xValues,
+ intervalESValue,
+ intervalESUnit as unitOfTime.Base,
+ timeZone
+ ),
};
-
- const rectAnnotations = [];
- if (domainStart !== domainMin) {
- rectAnnotations.push({
- coordinates: {
- x1: domainStart,
- },
- });
- }
- if (domainEnd !== domainMax) {
- rectAnnotations.push({
- coordinates: {
- x0: domainEnd,
- },
- });
- }
-
- const rectAnnotationStyle = {
- stroke: isDarkMode ? darkEuiTheme.euiColorLightShade : lightEuiTheme.euiColorDarkShade,
- strokeWidth: 0,
- opacity: isDarkMode ? 0.6 : 0.2,
- fill: isDarkMode ? darkEuiTheme.euiColorLightShade : lightEuiTheme.euiColorDarkShade,
- };
-
const tooltipProps = {
- headerFormatter: this.renderBarTooltip(xInterval, domainStart, domainEnd),
+ headerFormatter: renderEndzoneTooltip(xInterval, domainStart, domainEnd, this.formatXValue),
type: TooltipType.VerticalCursor,
};
@@ -313,19 +188,14 @@ export class DiscoverHistogram extends Component
-
-
+
0
? savedSearch.columns
diff --git a/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.test.ts b/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.test.ts
new file mode 100644
index 0000000000000..9ad19653a6c12
--- /dev/null
+++ b/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.test.ts
@@ -0,0 +1,43 @@
+/*
+ * 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 { getDefaultSort } from './get_default_sort';
+// @ts-ignore
+import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
+import { IndexPattern } from '../../../../kibana_services';
+
+describe('getDefaultSort function', function () {
+ let indexPattern: IndexPattern;
+ beforeEach(() => {
+ indexPattern = FixturesStubbedLogstashIndexPatternProvider() as IndexPattern;
+ });
+ test('should be a function', function () {
+ expect(typeof getDefaultSort === 'function').toBeTruthy();
+ });
+
+ test('should return default sort for an index pattern with timeFieldName', function () {
+ expect(getDefaultSort(indexPattern, 'desc')).toEqual([['time', 'desc']]);
+ expect(getDefaultSort(indexPattern, 'asc')).toEqual([['time', 'asc']]);
+ });
+
+ test('should return default sort for an index pattern without timeFieldName', function () {
+ delete indexPattern.timeFieldName;
+ expect(getDefaultSort(indexPattern, 'desc')).toEqual([]);
+ expect(getDefaultSort(indexPattern, 'asc')).toEqual([]);
+ });
+});
diff --git a/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.ts b/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.ts
index 634e3cfec3a0b..c1e4da0bab54d 100644
--- a/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.ts
+++ b/src/plugins/discover/public/application/angular/doc_table/lib/get_default_sort.ts
@@ -17,7 +17,6 @@
* under the License.
*/
import { IndexPattern } from '../../../../kibana_services';
-// @ts-ignore
import { isSortable } from './get_sort';
import { SortOrder } from '../components/table_header/helpers';
@@ -26,12 +25,12 @@ import { SortOrder } from '../components/table_header/helpers';
* the default sort is returned depending of the index pattern
*/
export function getDefaultSort(
- indexPattern: IndexPattern,
+ indexPattern: IndexPattern | undefined,
defaultSortOrder: string = 'desc'
): SortOrder[] {
- if (indexPattern.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) {
+ if (indexPattern?.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) {
return [[indexPattern.timeFieldName, defaultSortOrder]];
} else {
- return [['_score', defaultSortOrder]];
+ return [];
}
}
diff --git a/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.test.ts b/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.test.ts
new file mode 100644
index 0000000000000..1dbd31897d307
--- /dev/null
+++ b/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.test.ts
@@ -0,0 +1,51 @@
+/*
+ * 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 { getSortForSearchSource } from './get_sort_for_search_source';
+// @ts-ignore
+import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
+import { IndexPattern } from '../../../../kibana_services';
+import { SortOrder } from '../components/table_header/helpers';
+
+describe('getSortForSearchSource function', function () {
+ let indexPattern: IndexPattern;
+ beforeEach(() => {
+ indexPattern = FixturesStubbedLogstashIndexPatternProvider() as IndexPattern;
+ });
+ test('should be a function', function () {
+ expect(typeof getSortForSearchSource === 'function').toBeTruthy();
+ });
+
+ test('should return an object to use for searchSource when columns are given', function () {
+ const cols = [['bytes', 'desc']] as SortOrder[];
+ expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ bytes: 'desc' }]);
+ expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ bytes: 'desc' }]);
+ delete indexPattern.timeFieldName;
+ expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ bytes: 'desc' }]);
+ expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ bytes: 'desc' }]);
+ });
+
+ test('should return an object to use for searchSource when no columns are given', function () {
+ const cols = [] as SortOrder[];
+ expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ _doc: 'desc' }]);
+ expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ _doc: 'asc' }]);
+ delete indexPattern.timeFieldName;
+ expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ _score: 'desc' }]);
+ expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ _score: 'asc' }]);
+ });
+});
diff --git a/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.ts b/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.ts
index 6721f7a03584c..1244a0e229cdb 100644
--- a/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.ts
+++ b/src/plugins/discover/public/application/angular/doc_table/lib/get_sort_for_search_source.ts
@@ -19,7 +19,6 @@
import { EsQuerySortValue, IndexPattern } from '../../../../kibana_services';
import { SortOrder } from '../components/table_header/helpers';
import { getSort } from './get_sort';
-import { getDefaultSort } from './get_default_sort';
/**
* Prepares sort for search source, that's sending the request to ES
@@ -33,10 +32,13 @@ export function getSortForSearchSource(
indexPattern?: IndexPattern,
defaultDirection: string = 'desc'
): EsQuerySortValue[] {
- if (!sort || !indexPattern) {
- return [];
- } else if (Array.isArray(sort) && sort.length === 0) {
- sort = getDefaultSort(indexPattern, defaultDirection);
+ if (!sort || !indexPattern || (Array.isArray(sort) && sort.length === 0)) {
+ if (indexPattern?.timeFieldName) {
+ // sorting by index order
+ return [{ _doc: defaultDirection } as EsQuerySortValue];
+ } else {
+ return [{ _score: defaultDirection } as EsQuerySortValue];
+ }
}
const { timeFieldName } = indexPattern;
return getSort(sort, indexPattern).map((sortPair: Record) => {
diff --git a/src/plugins/discover/public/application/embeddable/search_embeddable.ts b/src/plugins/discover/public/application/embeddable/search_embeddable.ts
index b143afd1988e6..d0c3907d31242 100644
--- a/src/plugins/discover/public/application/embeddable/search_embeddable.ts
+++ b/src/plugins/discover/public/application/embeddable/search_embeddable.ts
@@ -21,9 +21,10 @@ import angular from 'angular';
import _ from 'lodash';
import { Subscription } from 'rxjs';
import { i18n } from '@kbn/i18n';
-import { UiActionsStart, APPLY_FILTER_TRIGGER } from '../../../../ui_actions/public';
+import { UiActionsStart } from '../../../../ui_actions/public';
import { RequestAdapter, Adapters } from '../../../../inspector/public';
import {
+ APPLY_FILTER_TRIGGER,
esFilters,
Filter,
TimeRange,
@@ -48,6 +49,7 @@ import {
import { SEARCH_EMBEDDABLE_TYPE } from './constants';
import { SavedSearch } from '../..';
import { SAMPLE_SIZE_SETTING, SORT_DEFAULT_ORDER_SETTING } from '../../../common';
+import { getDefaultSort } from '../angular/doc_table/lib/get_default_sort';
interface SearchScope extends ng.IScope {
columns?: string[];
@@ -200,6 +202,13 @@ export class SearchEmbeddable
const { searchSource } = this.savedSearch;
const indexPattern = (searchScope.indexPattern = searchSource.getField('index'))!;
+ if (!this.savedSearch.sort || !this.savedSearch.sort.length) {
+ this.savedSearch.sort = getDefaultSort(
+ indexPattern,
+ getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING, 'desc')
+ );
+ }
+
const timeRangeSearchSource = searchSource.create();
timeRangeSearchSource.setField('filter', () => {
if (!this.searchScope || !this.input.timeRange) return;
@@ -341,7 +350,14 @@ export class SearchEmbeddable
// If there is column or sort data on the panel, that means the original columns or sort settings have
// been overridden in a dashboard.
searchScope.columns = this.input.columns || this.savedSearch.columns;
- searchScope.sort = this.input.sort || this.savedSearch.sort;
+ const savedSearchSort =
+ this.savedSearch.sort && this.savedSearch.sort.length
+ ? this.savedSearch.sort
+ : getDefaultSort(
+ this.searchScope?.indexPattern,
+ getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING, 'desc')
+ );
+ searchScope.sort = this.input.sort || savedSearchSort;
searchScope.sharedItemTitle = this.panelTitle;
if (forceFetch || isFetchRequired) {
diff --git a/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts b/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts
index b2aa3a05d7eb0..4dec1f75ba322 100644
--- a/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts
+++ b/src/plugins/discover/public/application/helpers/get_sharing_data.test.ts
@@ -21,6 +21,7 @@ import { getSharingData } from './get_sharing_data';
import { IUiSettingsClient } from 'kibana/public';
import { createSearchSourceMock } from '../../../../data/common/search/search_source/mocks';
import { indexPatternMock } from '../../__mocks__/index_pattern';
+import { SORT_DEFAULT_ORDER_SETTING } from '../../../common';
describe('getSharingData', () => {
test('returns valid data for sharing', async () => {
@@ -29,7 +30,10 @@ describe('getSharingData', () => {
searchSourceMock,
{ columns: [] },
({
- get: () => {
+ get: (key: string) => {
+ if (key === SORT_DEFAULT_ORDER_SETTING) {
+ return 'desc';
+ }
return false;
},
} as unknown) as IUiSettingsClient,
@@ -57,7 +61,13 @@ describe('getSharingData', () => {
},
},
"script_fields": Object {},
- "sort": Array [],
+ "sort": Array [
+ Object {
+ "_score": Object {
+ "order": "desc",
+ },
+ },
+ ],
"stored_fields": undefined,
},
"index": "the-index-pattern-title",
diff --git a/src/plugins/embeddable/common/types.ts b/src/plugins/embeddable/common/types.ts
index 8965446cc85fa..d893724f616d2 100644
--- a/src/plugins/embeddable/common/types.ts
+++ b/src/plugins/embeddable/common/types.ts
@@ -18,8 +18,6 @@
*/
import { PersistableStateService, SerializableState } from '../../kibana_utils/common';
-import { Query, TimeRange } from '../../data/common/query';
-import { Filter } from '../../data/common/es_query/filters';
export enum ViewMode {
EDIT = 'edit',
@@ -53,21 +51,6 @@ export type EmbeddableInput = {
*/
disableTriggers?: boolean;
- /**
- * Time range of the chart.
- */
- timeRange?: TimeRange;
-
- /**
- * Visualization query string used to narrow down results.
- */
- query?: Query;
-
- /**
- * Visualization filters used to narrow down results.
- */
- filters?: Filter[];
-
/**
* Search session id to group searches
*/
diff --git a/src/plugins/embeddable/public/bootstrap.ts b/src/plugins/embeddable/public/bootstrap.ts
index 5c95214ef591b..efaff42c19e2f 100644
--- a/src/plugins/embeddable/public/bootstrap.ts
+++ b/src/plugins/embeddable/public/bootstrap.ts
@@ -18,18 +18,24 @@
*/
import { UiActionsSetup } from '../../ui_actions/public';
import {
- contextMenuTrigger,
- panelBadgeTrigger,
- EmbeddableContext,
- CONTEXT_MENU_TRIGGER,
- PANEL_BADGE_TRIGGER,
ACTION_ADD_PANEL,
ACTION_CUSTOMIZE_PANEL,
- ACTION_INSPECT_PANEL,
- REMOVE_PANEL_ACTION,
ACTION_EDIT_PANEL,
- panelNotificationTrigger,
+ ACTION_INSPECT_PANEL,
+ CONTEXT_MENU_TRIGGER,
+ contextMenuTrigger,
+ EmbeddableContext,
+ PANEL_BADGE_TRIGGER,
PANEL_NOTIFICATION_TRIGGER,
+ panelBadgeTrigger,
+ panelNotificationTrigger,
+ RangeSelectContext,
+ REMOVE_PANEL_ACTION,
+ SELECT_RANGE_TRIGGER,
+ selectRangeTrigger,
+ ValueClickContext,
+ VALUE_CLICK_TRIGGER,
+ valueClickTrigger,
} from './lib';
declare module '../../ui_actions/public' {
@@ -37,6 +43,8 @@ declare module '../../ui_actions/public' {
[CONTEXT_MENU_TRIGGER]: EmbeddableContext;
[PANEL_BADGE_TRIGGER]: EmbeddableContext;
[PANEL_NOTIFICATION_TRIGGER]: EmbeddableContext;
+ [SELECT_RANGE_TRIGGER]: RangeSelectContext;
+ [VALUE_CLICK_TRIGGER]: ValueClickContext;
}
export interface ActionContextMapping {
@@ -56,4 +64,6 @@ export const bootstrap = (uiActions: UiActionsSetup) => {
uiActions.registerTrigger(contextMenuTrigger);
uiActions.registerTrigger(panelBadgeTrigger);
uiActions.registerTrigger(panelNotificationTrigger);
+ uiActions.registerTrigger(selectRangeTrigger);
+ uiActions.registerTrigger(valueClickTrigger);
};
diff --git a/src/plugins/embeddable/public/index.ts b/src/plugins/embeddable/public/index.ts
index 0fc7c7965010b..d537ef2bd0c5c 100644
--- a/src/plugins/embeddable/public/index.ts
+++ b/src/plugins/embeddable/public/index.ts
@@ -65,6 +65,8 @@ export {
PanelNotFoundError,
PanelState,
PropertySpec,
+ SELECT_RANGE_TRIGGER,
+ VALUE_CLICK_TRIGGER,
ViewMode,
withEmbeddableSubscription,
SavedObjectEmbeddableInput,
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable.test.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable.test.tsx
index c7c71656bceb2..c0e13a84066ca 100644
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable.test.tsx
+++ b/src/plugins/embeddable/public/lib/embeddables/embeddable.test.tsx
@@ -24,8 +24,10 @@ import { Embeddable } from './embeddable';
import { EmbeddableOutput, EmbeddableInput } from './i_embeddable';
import { ViewMode } from '../types';
import { ContactCardEmbeddable } from '../test_samples/embeddables/contact_card/contact_card_embeddable';
-import { FilterableEmbeddable } from '../test_samples/embeddables/filterable_embeddable';
-import type { Filter } from '../../../../data/public';
+import {
+ MockFilter,
+ FilterableEmbeddable,
+} from '../test_samples/embeddables/filterable_embeddable';
class TestClass {
constructor() {}
@@ -83,7 +85,7 @@ test('Embeddable reload is called if lastReloadRequest input time changes', asyn
test('Embeddable reload is called if lastReloadRequest input time changed and new input is used', async () => {
const hello = new FilterableEmbeddable({ id: '123', filters: [], lastReloadRequestTime: 0 });
- const aFilter = ({} as unknown) as Filter;
+ const aFilter = ({} as unknown) as MockFilter;
hello.reload = jest.fn(() => {
// when reload is called embeddable already has new input
expect(hello.getInput().filters).toEqual([aFilter]);
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx
index 0361939fd07e6..cb78fac5471a9 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_action.test.tsx
@@ -20,6 +20,7 @@
import { ViewMode, EmbeddableOutput, isErrorEmbeddable } from '../../../../';
import { AddPanelAction } from './add_panel_action';
import {
+ MockFilter,
FILTERABLE_EMBEDDABLE,
FilterableEmbeddable,
FilterableEmbeddableInput,
@@ -28,7 +29,6 @@ import { FilterableEmbeddableFactory } from '../../../../test_samples/embeddable
import { FilterableContainer } from '../../../../test_samples/embeddables/filterable_container';
import { coreMock } from '../../../../../../../../core/public/mocks';
import { ContactCardEmbeddable } from '../../../../test_samples';
-import { esFilters, Filter } from '../../../../../../../../plugins/data/public';
import { EmbeddableStart } from '../../../../../plugin';
import { embeddablePluginMock } from '../../../../../mocks';
import { defaultTrigger } from '../../../../../../../ui_actions/public/triggers';
@@ -51,8 +51,8 @@ beforeEach(async () => {
() => null
);
- const derivedFilter: Filter = {
- $state: { store: esFilters.FilterStateStore.APP_STATE },
+ const derivedFilter: MockFilter = {
+ $state: { store: 'appState' },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
index eb83641448986..b784a46127305 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
@@ -29,7 +29,6 @@ import {
import { inspectorPluginMock } from '../../../../../../../plugins/inspector/public/mocks';
import { EmbeddableOutput, isErrorEmbeddable, ErrorEmbeddable } from '../../../embeddables';
import { of } from '../../../../tests/helpers';
-import { esFilters } from '../../../../../../../plugins/data/public';
import { embeddablePluginMock } from '../../../../mocks';
import { EmbeddableStart } from '../../../../plugin';
@@ -43,7 +42,7 @@ const setupTests = async () => {
panels: {},
filters: [
{
- $state: { store: esFilters.FilterStateStore.APP_STATE },
+ $state: { store: 'appState' },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
},
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx
index dea4a88bda082..ce6a1cc20fc4d 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.test.tsx
@@ -21,6 +21,7 @@ import { EmbeddableOutput, isErrorEmbeddable } from '../../../';
import { RemovePanelAction } from './remove_panel_action';
import { EmbeddableStart } from '../../../../plugin';
import {
+ MockFilter,
FILTERABLE_EMBEDDABLE,
FilterableEmbeddable,
FilterableEmbeddableInput,
@@ -29,7 +30,6 @@ import { FilterableEmbeddableFactory } from '../../../test_samples/embeddables/f
import { FilterableContainer } from '../../../test_samples/embeddables/filterable_container';
import { ViewMode } from '../../../types';
import { ContactCardEmbeddable } from '../../../test_samples/embeddables/contact_card/contact_card_embeddable';
-import { esFilters, Filter } from '../../../../../../../plugins/data/public';
import { embeddablePluginMock } from '../../../../mocks';
const { setup, doStart } = embeddablePluginMock.createInstance();
@@ -39,8 +39,8 @@ let container: FilterableContainer;
let embeddable: FilterableEmbeddable;
beforeEach(async () => {
- const derivedFilter: Filter = {
- $state: { store: esFilters.FilterStateStore.APP_STATE },
+ const derivedFilter: MockFilter = {
+ $state: { store: 'appState' },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
diff --git a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts
index cbaeddf472d52..be034d125dcee 100644
--- a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts
+++ b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts
@@ -23,6 +23,7 @@ import { EmbeddableStateTransfer } from '.';
import { ApplicationStart, PublicAppInfo } from '../../../../../core/public';
import { EMBEDDABLE_EDITOR_STATE_KEY, EMBEDDABLE_PACKAGE_STATE_KEY } from './types';
import { EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY } from './embeddable_state_transfer';
+import { Subject } from 'rxjs';
const createStorage = (): Storage => {
const createMockStore = () => {
@@ -46,16 +47,24 @@ const createStorage = (): Storage => {
describe('embeddable state transfer', () => {
let application: jest.Mocked;
let stateTransfer: EmbeddableStateTransfer;
+ let currentAppId$: Subject;
let store: Storage;
const destinationApp = 'superUltraVisualize';
const originatingApp = 'superUltraTestDashboard';
beforeEach(() => {
+ currentAppId$ = new Subject();
+ currentAppId$.next(originatingApp);
const core = coreMock.createStart();
application = core.application;
store = createStorage();
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, undefined, store);
+ stateTransfer = new EmbeddableStateTransfer(
+ application.navigateToApp,
+ currentAppId$,
+ undefined,
+ store
+ );
});
it('cannot fetch app name when given no app list', async () => {
@@ -67,7 +76,7 @@ describe('embeddable state transfer', () => {
['testId', { title: 'State Transfer Test App Hello' } as PublicAppInfo],
['testId2', { title: 'State Transfer Test App Goodbye' } as PublicAppInfo],
]);
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, appsList);
+ stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, currentAppId$, appsList);
expect(stateTransfer.getAppNameFromId('kibanana')).toBeUndefined();
});
@@ -76,7 +85,7 @@ describe('embeddable state transfer', () => {
['testId', { title: 'State Transfer Test App Hello' } as PublicAppInfo],
['testId2', { title: 'State Transfer Test App Goodbye' } as PublicAppInfo],
]);
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, appsList);
+ stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, currentAppId$, appsList);
expect(stateTransfer.getAppNameFromId('testId')).toBe('State Transfer Test App Hello');
expect(stateTransfer.getAppNameFromId('testId2')).toBe('State Transfer Test App Goodbye');
});
@@ -107,6 +116,13 @@ describe('embeddable state transfer', () => {
});
});
+ it('sets isTransferInProgress to true when sending an outgoing editor state', async () => {
+ await stateTransfer.navigateToEditor(destinationApp, { state: { originatingApp } });
+ expect(stateTransfer.isTransferInProgress).toEqual(true);
+ currentAppId$.next(destinationApp);
+ expect(stateTransfer.isTransferInProgress).toEqual(false);
+ });
+
it('can send an outgoing embeddable package state', async () => {
await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, {
state: { type: 'coolestType', input: { savedObjectId: '150' } },
@@ -135,6 +151,15 @@ describe('embeddable state transfer', () => {
});
});
+ it('sets isTransferInProgress to true when sending an outgoing embeddable package state', async () => {
+ await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, {
+ state: { type: 'coolestType', input: { savedObjectId: '150' } },
+ });
+ expect(stateTransfer.isTransferInProgress).toEqual(true);
+ currentAppId$.next(destinationApp);
+ expect(stateTransfer.isTransferInProgress).toEqual(false);
+ });
+
it('can fetch an incoming editor state', async () => {
store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
[EMBEDDABLE_EDITOR_STATE_KEY]: { originatingApp: 'superUltraTestDashboard' },
diff --git a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts
index 0b34bea810520..92900059668db 100644
--- a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts
+++ b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts
@@ -38,14 +38,20 @@ export const EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY = 'EMBEDDABLE_STATE_TRANSFER'
* @public
*/
export class EmbeddableStateTransfer {
+ public isTransferInProgress: boolean;
private storage: Storage;
constructor(
private navigateToApp: ApplicationStart['navigateToApp'],
+ currentAppId$: ApplicationStart['currentAppId$'],
private appList?: ReadonlyMap | undefined,
customStorage?: Storage
) {
this.storage = customStorage ? customStorage : new Storage(sessionStorage);
+ this.isTransferInProgress = false;
+ currentAppId$.subscribe(() => {
+ this.isTransferInProgress = false;
+ });
}
/**
@@ -105,6 +111,7 @@ export class EmbeddableStateTransfer {
state: EmbeddableEditorState;
}
): Promise {
+ this.isTransferInProgress = true;
await this.navigateToWithState(appId, EMBEDDABLE_EDITOR_STATE_KEY, {
...options,
appendToExistingState: true,
@@ -119,6 +126,7 @@ export class EmbeddableStateTransfer {
appId: string,
options?: { path?: string; state: EmbeddablePackageState }
): Promise {
+ this.isTransferInProgress = true;
await this.navigateToWithState(appId, EMBEDDABLE_PACKAGE_STATE_KEY, {
...options,
appendToExistingState: true,
diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/contact_card/contact_card_exportable_embeddable.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/contact_card/contact_card_exportable_embeddable.tsx
index 338eb4877a50a..00429c8df0cb1 100644
--- a/src/plugins/embeddable/public/lib/test_samples/embeddables/contact_card/contact_card_exportable_embeddable.tsx
+++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/contact_card/contact_card_exportable_embeddable.tsx
@@ -23,18 +23,21 @@ export class ContactCardExportableEmbeddable extends ContactCardEmbeddable {
public getInspectorAdapters = () => {
return {
tables: {
- layer1: {
- type: 'datatable',
- columns: [
- { id: 'firstName', name: 'First Name' },
- { id: 'originalLastName', name: 'Last Name' },
- ],
- rows: [
- {
- firstName: this.getInput().firstName,
- orignialLastName: this.getInput().lastName,
- },
- ],
+ allowCsvExport: true,
+ tables: {
+ layer1: {
+ type: 'datatable',
+ columns: [
+ { id: 'firstName', name: 'First Name' },
+ { id: 'originalLastName', name: 'Last Name' },
+ ],
+ rows: [
+ {
+ firstName: this.getInput().firstName,
+ orignialLastName: this.getInput().lastName,
+ },
+ ],
+ },
},
},
};
diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx
index db71b94ac855f..23696612fd82a 100644
--- a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx
+++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_container.tsx
@@ -18,13 +18,13 @@
*/
import { Container, ContainerInput } from '../../containers';
-import { Filter } from '../../../../../data/public';
import { EmbeddableStart } from '../../../plugin';
+import { MockFilter } from './filterable_embeddable';
export const FILTERABLE_CONTAINER = 'FILTERABLE_CONTAINER';
export interface FilterableContainerInput extends ContainerInput {
- filters: Filter[];
+ filters: MockFilter[];
}
/**
@@ -33,7 +33,7 @@ export interface FilterableContainerInput extends ContainerInput {
* here instead
*/
export type InheritedChildrenInput = {
- filters: Filter[];
+ filters: MockFilter[];
id?: string;
};
diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx
index fd6ea3b9aa2b2..99d21198dd151 100644
--- a/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx
+++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/filterable_embeddable.tsx
@@ -19,12 +19,18 @@
import { IContainer } from '../../containers';
import { EmbeddableOutput, EmbeddableInput, Embeddable } from '../../embeddables';
-import { Filter } from '../../../../../data/public';
+
+/** @internal */
+export interface MockFilter {
+ $state?: any;
+ meta: any;
+ query?: any;
+}
export const FILTERABLE_EMBEDDABLE = 'FILTERABLE_EMBEDDABLE';
export interface FilterableEmbeddableInput extends EmbeddableInput {
- filters: Filter[];
+ filters: MockFilter[];
}
export class FilterableEmbeddable extends Embeddable {
diff --git a/src/plugins/embeddable/public/lib/triggers/triggers.ts b/src/plugins/embeddable/public/lib/triggers/triggers.ts
index c3b1496b8eca8..d9fb063a5bb56 100644
--- a/src/plugins/embeddable/public/lib/triggers/triggers.ts
+++ b/src/plugins/embeddable/public/lib/triggers/triggers.ts
@@ -22,8 +22,8 @@ import { Datatable } from '../../../../expressions';
import { Trigger, RowClickContext } from '../../../../ui_actions/public';
import { IEmbeddable } from '..';
-export interface EmbeddableContext {
- embeddable: IEmbeddable;
+export interface EmbeddableContext {
+ embeddable: T;
}
export interface ValueClickContext {
@@ -88,6 +88,28 @@ export const panelNotificationTrigger: Trigger<'PANEL_NOTIFICATION_TRIGGER'> = {
}),
};
+export const SELECT_RANGE_TRIGGER = 'SELECT_RANGE_TRIGGER';
+export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> = {
+ id: SELECT_RANGE_TRIGGER,
+ title: i18n.translate('embeddableApi.selectRangeTrigger.title', {
+ defaultMessage: 'Range selection',
+ }),
+ description: i18n.translate('embeddableApi.selectRangeTrigger.description', {
+ defaultMessage: 'A range of values on the visualization',
+ }),
+};
+
+export const VALUE_CLICK_TRIGGER = 'VALUE_CLICK_TRIGGER';
+export const valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'> = {
+ id: VALUE_CLICK_TRIGGER,
+ title: i18n.translate('embeddableApi.valueClickTrigger.title', {
+ defaultMessage: 'Single click',
+ }),
+ description: i18n.translate('embeddableApi.valueClickTrigger.description', {
+ defaultMessage: 'A data point click on the visualization',
+ }),
+};
+
export const isValueClickTriggerContext = (
context: ChartActionContext
): context is ValueClickContext => context.data && 'data' in context.data;
diff --git a/src/plugins/embeddable/public/mocks.tsx b/src/plugins/embeddable/public/mocks.tsx
index df24d9c0393fe..c41ecaabe8479 100644
--- a/src/plugins/embeddable/public/mocks.tsx
+++ b/src/plugins/embeddable/public/mocks.tsx
@@ -34,7 +34,6 @@ import { coreMock } from '../../../core/public/mocks';
import { UiActionsService } from './lib/ui_actions';
import { CoreStart } from '../../../core/public';
import { Start as InspectorStart } from '../../inspector/public';
-import { dataPluginMock } from '../../data/public/mocks';
import { inspectorPluginMock } from '../../inspector/public/mocks';
import { uiActionsPluginMock } from '../../ui_actions/public/mocks';
@@ -136,13 +135,11 @@ const createInstance = (setupPlugins: Partial = {})
const plugin = new EmbeddablePublicPlugin({} as any);
const setup = plugin.setup(coreMock.createSetup(), {
uiActions: setupPlugins.uiActions || uiActionsPluginMock.createSetupContract(),
- data: dataPluginMock.createSetupContract(),
});
const doStart = (startPlugins: Partial = {}) =>
plugin.start(coreMock.createStart(), {
uiActions: startPlugins.uiActions || uiActionsPluginMock.createStartContract(),
inspector: inspectorPluginMock.createStartContract(),
- data: dataPluginMock.createStartContract(),
});
return {
plugin,
diff --git a/src/plugins/embeddable/public/plugin.tsx b/src/plugins/embeddable/public/plugin.tsx
index 5118a1a8818c0..a417fb3938b8a 100644
--- a/src/plugins/embeddable/public/plugin.tsx
+++ b/src/plugins/embeddable/public/plugin.tsx
@@ -19,7 +19,6 @@
import React from 'react';
import { Subscription } from 'rxjs';
import { identity } from 'lodash';
-import { DataPublicPluginSetup, DataPublicPluginStart } from '../../data/public';
import { getSavedObjectFinder, showSaveModal } from '../../saved_objects/public';
import { UiActionsSetup, UiActionsStart } from '../../ui_actions/public';
import { Start as InspectorStart } from '../../inspector/public';
@@ -62,12 +61,10 @@ import {
} from '../common/lib';
export interface EmbeddableSetupDependencies {
- data: DataPublicPluginSetup;
uiActions: UiActionsSetup;
}
export interface EmbeddableStartDependencies {
- data: DataPublicPluginStart;
uiActions: UiActionsStart;
inspector: InspectorStart;
}
@@ -144,7 +141,7 @@ export class EmbeddablePublicPlugin implements Plugin {
this.embeddableFactories.set(
@@ -161,6 +158,7 @@ export class EmbeddablePublicPlugin implements Plugin
storage
- ? new EmbeddableStateTransfer(core.application.navigateToApp, this.appList, storage)
+ ? new EmbeddableStateTransfer(
+ core.application.navigateToApp,
+ core.application.currentAppId$,
+ this.appList,
+ storage
+ )
: this.stateTransferService,
EmbeddablePanel: getEmbeddablePanelHoc(),
telemetry: getTelemetryFunction(commonContract),
diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md
index 60b694d628b78..a401795c498b3 100644
--- a/src/plugins/embeddable/public/public.api.md
+++ b/src/plugins/embeddable/public/public.api.md
@@ -8,48 +8,29 @@ import { Action } from 'history';
import { Action as Action_3 } from 'src/plugins/ui_actions/public';
import { ActionExecutionContext as ActionExecutionContext_2 } from 'src/plugins/ui_actions/public';
import { ApiResponse } from '@elastic/elasticsearch/lib/Transport';
-import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch';
import { ApplicationStart as ApplicationStart_2 } from 'kibana/public';
-import { Assign } from '@kbn/utility-types';
-import { BehaviorSubject } from 'rxjs';
-import { BfetchPublicSetup } from 'src/plugins/bfetch/public';
import Boom from '@hapi/boom';
import { ConfigDeprecationProvider } from '@kbn/config';
-import { CoreSetup as CoreSetup_2 } from 'src/core/public';
-import { CoreSetup as CoreSetup_3 } from 'kibana/public';
-import { CoreStart as CoreStart_2 } from 'kibana/public';
import * as CSS from 'csstype';
-import { DatatableColumn as DatatableColumn_2 } from 'src/plugins/expressions';
import { EmbeddableStart as EmbeddableStart_2 } from 'src/plugins/embeddable/public/plugin';
-import { Ensure } from '@kbn/utility-types';
import { EnvironmentMode } from '@kbn/config';
-import { ErrorToastOptions as ErrorToastOptions_2 } from 'src/core/public/notifications';
import { EuiBreadcrumb } from '@elastic/eui';
import { EuiButtonEmptyProps } from '@elastic/eui';
-import { EuiComboBoxProps } from '@elastic/eui';
import { EuiConfirmModalProps } from '@elastic/eui';
import { EuiContextMenuPanelDescriptor } from '@elastic/eui';
import { EuiFlyoutSize } from '@elastic/eui';
import { EuiGlobalToastListToast } from '@elastic/eui';
import { EventEmitter } from 'events';
-import { ExpressionAstExpression } from 'src/plugins/expressions/common';
import { History } from 'history';
import { Href } from 'history';
-import { HttpSetup as HttpSetup_2 } from 'kibana/public';
import { I18nStart as I18nStart_2 } from 'src/core/public';
import { IconType } from '@elastic/eui';
-import { ISearchOptions } from 'src/plugins/data/public';
-import { ISearchSource } from 'src/plugins/data/public';
-import { IStorageWrapper as IStorageWrapper_2 } from 'src/plugins/kibana_utils/public';
-import { IUiSettingsClient as IUiSettingsClient_2 } from 'src/core/public';
import { KibanaClient } from '@elastic/elasticsearch/api/kibana';
import { Location } from 'history';
import { LocationDescriptorObject } from 'history';
import { Logger } from '@kbn/logging';
import { LogMeta } from '@kbn/logging';
import { MaybePromise } from '@kbn/utility-types';
-import { Moment } from 'moment';
-import { NameList } from 'elasticsearch';
import { NotificationsStart as NotificationsStart_2 } from 'src/core/public';
import { Observable } from 'rxjs';
import { Optional } from '@kbn/utility-types';
@@ -57,39 +38,23 @@ import { OverlayStart as OverlayStart_2 } from 'src/core/public';
import { PackageInfo } from '@kbn/config';
import { Path } from 'history';
import { PluginInitializerContext } from 'src/core/public';
-import { PluginInitializerContext as PluginInitializerContext_3 } from 'kibana/public';
import * as PropTypes from 'prop-types';
-import { PublicContract } from '@kbn/utility-types';
import { PublicMethodsOf } from '@kbn/utility-types';
import { PublicUiSettingsParams } from 'src/core/server/types';
import React from 'react';
import { RecursiveReadonly } from '@kbn/utility-types';
-import { RequestAdapter as RequestAdapter_2 } from 'src/plugins/inspector/common';
-import { Required } from '@kbn/utility-types';
import * as Rx from 'rxjs';
-import { SavedObject as SavedObject_2 } from 'kibana/server';
-import { SavedObject as SavedObject_3 } from 'src/core/server';
import { SavedObjectAttributes } from 'kibana/server';
import { SavedObjectAttributes as SavedObjectAttributes_2 } from 'src/core/public';
import { SavedObjectAttributes as SavedObjectAttributes_3 } from 'kibana/public';
-import { SavedObjectsClientContract as SavedObjectsClientContract_3 } from 'src/core/public';
-import { SavedObjectsFindOptions as SavedObjectsFindOptions_3 } from 'kibana/public';
-import { SavedObjectsFindResponse as SavedObjectsFindResponse_2 } from 'kibana/server';
-import { Search } from '@elastic/elasticsearch/api/requestParams';
-import { SearchResponse } from 'elasticsearch';
-import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common';
import { ShallowPromise } from '@kbn/utility-types';
import { SimpleSavedObject as SimpleSavedObject_2 } from 'src/core/public';
import { Start as Start_2 } from 'src/plugins/inspector/public';
-import { StartServicesAccessor as StartServicesAccessor_2 } from 'kibana/public';
-import { ToastInputFields as ToastInputFields_2 } from 'src/core/public/notifications';
-import { ToastsSetup as ToastsSetup_2 } from 'kibana/public';
import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport';
import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport';
import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport';
import { TypeOf } from '@kbn/config-schema';
import { UiComponent } from 'src/plugins/kibana_utils/public';
-import { UiCounterMetricType } from '@kbn/analytics';
import { UnregisterCallback } from 'history';
import { UserProvidedValues } from 'src/core/server/types';
@@ -109,10 +74,6 @@ export const ACTION_EDIT_PANEL = "editPanel";
export interface Adapters {
// (undocumented)
[key: string]: any;
- // Warning: (ae-forgotten-export) The symbol "DataAdapter" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- data?: DataAdapter;
// Warning: (ae-forgotten-export) The symbol "RequestAdapter" needs to be exported by the entry point index.d.ts
//
// (undocumented)
@@ -352,7 +313,7 @@ export abstract class Embeddable {
+export class EmbeddableChildPanel extends React.Component {
constructor(props: EmbeddableChildPanelProps);
// (undocumented)
[panel: string]: any;
@@ -385,9 +346,9 @@ export interface EmbeddableChildPanelProps {
// Warning: (ae-missing-release-tag) "EmbeddableContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
-export interface EmbeddableContext {
+export interface EmbeddableContext {
// (undocumented)
- embeddable: IEmbeddable;
+ embeddable: T;
}
// @public
@@ -448,9 +409,6 @@ export type EmbeddableInput = {
enhancements?: SerializableState;
disabledActions?: string[];
disableTriggers?: boolean;
- timeRange?: TimeRange;
- query?: Query;
- filters?: Filter[];
searchSessionId?: string;
};
@@ -505,7 +463,7 @@ export interface EmbeddablePackageState {
// Warning: (ae-missing-release-tag) "EmbeddablePanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
-export class EmbeddablePanel extends React.Component {
+export class EmbeddablePanel extends React.Component {
constructor(props: Props);
// (undocumented)
closeMyContextMenuPanel: () => void;
@@ -575,10 +533,6 @@ export interface EmbeddableSetup {
//
// @public (undocumented)
export interface EmbeddableSetupDependencies {
- // Warning: (ae-forgotten-export) The symbol "DataPublicPluginSetup" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- data: DataPublicPluginSetup;
// Warning: (ae-forgotten-export) The symbol "UiActionsSetup" needs to be exported by the entry point index.d.ts
//
// (undocumented)
@@ -614,10 +568,6 @@ export interface EmbeddableStart extends PersistableStateService | undefined, customStorage?: Storage);
+ constructor(navigateToApp: ApplicationStart['navigateToApp'], currentAppId$: ApplicationStart['currentAppId$'], appList?: ReadonlyMap | undefined, customStorage?: Storage);
// (undocumented)
clearEditorState(): void;
getAppNameFromId: (appId: string) => string | undefined;
getIncomingEditorState(removeAfterFetch?: boolean): EmbeddableEditorState | undefined;
getIncomingEmbeddablePackage(removeAfterFetch?: boolean): EmbeddablePackageState | undefined;
+ // (undocumented)
+ isTransferInProgress: boolean;
// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ApplicationStart"
navigateToEditor(appId: string, options?: {
path?: string;
@@ -717,7 +669,7 @@ export interface IEmbeddable context is EmbeddableContext;
+export const isContextMenuTriggerContext: (context: unknown) => context is EmbeddableContext>;
// Warning: (ae-missing-release-tag) "isEmbeddable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -871,6 +823,16 @@ export interface SavedObjectEmbeddableInput extends EmbeddableInput {
savedObjectId: string;
}
+// Warning: (ae-missing-release-tag) "SELECT_RANGE_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export const SELECT_RANGE_TRIGGER = "SELECT_RANGE_TRIGGER";
+
+// Warning: (ae-missing-release-tag) "VALUE_CLICK_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export const VALUE_CLICK_TRIGGER = "VALUE_CLICK_TRIGGER";
+
// Warning: (ae-missing-release-tag) "ValueClickContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -914,10 +876,7 @@ export const withEmbeddableSubscription: {
test('Explicit embeddable input mapped to undefined will default to inherited', async () => {
const { start } = await creatHelloWorldContainerAndEmbeddable();
- const derivedFilter: Filter = {
- $state: { store: esFilters.FilterStateStore.APP_STATE },
+ const derivedFilter: MockFilter = {
+ $state: { store: 'appState' },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
diff --git a/src/plugins/embeddable/public/tests/explicit_input.test.ts b/src/plugins/embeddable/public/tests/explicit_input.test.ts
index 24785dd50a032..531fbcee94db6 100644
--- a/src/plugins/embeddable/public/tests/explicit_input.test.ts
+++ b/src/plugins/embeddable/public/tests/explicit_input.test.ts
@@ -20,6 +20,7 @@
import { skip } from 'rxjs/operators';
import { testPlugin } from './test_plugin';
import {
+ MockFilter,
FILTERABLE_EMBEDDABLE,
FilterableEmbeddableInput,
} from '../lib/test_samples/embeddables/filterable_embeddable';
@@ -34,7 +35,6 @@ import { FilterableContainer } from '../lib/test_samples/embeddables/filterable_
import { isErrorEmbeddable } from '../lib';
import { HelloWorldContainer } from '../lib/test_samples/embeddables/hello_world_container';
import { coreMock } from '../../../../core/public/mocks';
-import { esFilters, Filter } from '../../../../plugins/data/public';
import { createEmbeddablePanelMock } from '../mocks';
const { setup, doStart, coreStart, uiActions } = testPlugin(
@@ -56,8 +56,8 @@ setup.registerEmbeddableFactory(
const start = doStart();
test('Explicit embeddable input mapped to undefined will default to inherited', async () => {
- const derivedFilter: Filter = {
- $state: { store: esFilters.FilterStateStore.APP_STATE },
+ const derivedFilter: MockFilter = {
+ $state: { store: 'appState' },
meta: { disabled: false, alias: 'name', negate: false },
query: { match: {} },
};
diff --git a/src/plugins/embeddable/public/tests/test_plugin.ts b/src/plugins/embeddable/public/tests/test_plugin.ts
index 2c298b437a118..74bb70e913bcc 100644
--- a/src/plugins/embeddable/public/tests/test_plugin.ts
+++ b/src/plugins/embeddable/public/tests/test_plugin.ts
@@ -21,7 +21,6 @@ import { CoreSetup, CoreStart } from 'src/core/public';
import { UiActionsStart } from '../../../ui_actions/public';
import { uiActionsPluginMock } from '../../../ui_actions/public/mocks';
import { inspectorPluginMock } from '../../../inspector/public/mocks';
-import { dataPluginMock } from '../../../data/public/mocks';
import { coreMock } from '../../../../core/public/mocks';
import { EmbeddablePublicPlugin, EmbeddableSetup, EmbeddableStart } from '../plugin';
@@ -42,7 +41,6 @@ export const testPlugin = (
const initializerContext = {} as any;
const plugin = new EmbeddablePublicPlugin(initializerContext);
const setup = plugin.setup(coreSetup, {
- data: dataPluginMock.createSetupContract(),
uiActions: uiActions.setup,
});
@@ -53,7 +51,6 @@ export const testPlugin = (
setup,
doStart: (anotherCoreStart: CoreStart = coreStart) => {
const start = plugin.start(anotherCoreStart, {
- data: dataPluginMock.createStartContract(),
inspector: inspectorPluginMock.createStartContract(),
uiActions: uiActionsPluginMock.createStartContract(),
});
diff --git a/src/plugins/es_ui_shared/public/components/cron_editor/cron_editor.tsx b/src/plugins/es_ui_shared/public/components/cron_editor/cron_editor.tsx
index 72e2f51c37e4c..19af93b67aca0 100644
--- a/src/plugins/es_ui_shared/public/components/cron_editor/cron_editor.tsx
+++ b/src/plugins/es_ui_shared/public/components/cron_editor/cron_editor.tsx
@@ -67,6 +67,7 @@ interface Props {
fieldToPreferredValueMap: FieldToValueMap;
frequency: Frequency;
}) => void;
+ autoFocus?: boolean;
}
type State = FieldToValueMap;
@@ -234,6 +235,7 @@ export class CronEditor extends Component {
fullWidth
>
) =>
diff --git a/src/plugins/expressions/common/execution/execution.test.ts b/src/plugins/expressions/common/execution/execution.test.ts
index 10a18d0cbf435..9819c721d7275 100644
--- a/src/plugins/expressions/common/execution/execution.test.ts
+++ b/src/plugins/expressions/common/execution/execution.test.ts
@@ -220,10 +220,10 @@ describe('Execution', () => {
});
describe('inspector adapters', () => {
- test('by default, "data" and "requests" inspector adapters are available', async () => {
+ test('by default, "tables" and "requests" inspector adapters are available', async () => {
const { result } = (await run('introspectContext key="inspectorAdapters"')) as any;
expect(result).toMatchObject({
- data: expect.any(Object),
+ tables: expect.any(Object),
requests: expect.any(Object),
});
});
diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts
index c5c7d82e223b0..609022f8a55c0 100644
--- a/src/plugins/expressions/common/execution/execution.ts
+++ b/src/plugins/expressions/common/execution/execution.ts
@@ -23,7 +23,7 @@ import { Executor } from '../executor';
import { createExecutionContainer, ExecutionContainer } from './container';
import { createError } from '../util';
import { abortSignalToPromise, Defer, now } from '../../../kibana_utils/common';
-import { RequestAdapter, DataAdapter, Adapters } from '../../../inspector/common';
+import { RequestAdapter, Adapters } from '../../../inspector/common';
import { isExpressionValueError, ExpressionValueError } from '../expression_types/specs/error';
import {
ExpressionAstExpression,
@@ -34,11 +34,12 @@ import {
ExpressionAstNode,
} from '../ast';
import { ExecutionContext, DefaultInspectorAdapters } from './types';
-import { getType, ExpressionValue } from '../expression_types';
+import { getType, ExpressionValue, Datatable } from '../expression_types';
import { ArgumentType, ExpressionFunction } from '../expression_functions';
import { getByAlias } from '../util/get_by_alias';
import { ExecutionContract } from './execution_contract';
import { ExpressionExecutionParams } from '../service';
+import { TablesAdapter } from '../util/tables_adapter';
/**
* AbortController is not available in Node until v15, so we
@@ -72,7 +73,7 @@ export interface ExecutionParams {
const createDefaultInspectorAdapters = (): DefaultInspectorAdapters => ({
requests: new RequestAdapter(),
- data: new DataAdapter(),
+ tables: new TablesAdapter(),
});
export class Execution<
@@ -166,6 +167,9 @@ export class Execution<
ast,
});
+ const inspectorAdapters =
+ execution.params.inspectorAdapters || createDefaultInspectorAdapters();
+
this.context = {
getSearchContext: () => this.execution.params.searchContext || {},
getSearchSessionId: () => execution.params.searchSessionId,
@@ -175,7 +179,10 @@ export class Execution<
variables: execution.params.variables || {},
types: executor.getTypes(),
abortSignal: this.abortController.signal,
- inspectorAdapters: execution.params.inspectorAdapters || createDefaultInspectorAdapters(),
+ inspectorAdapters,
+ logDatatable: (name: string, datatable: Datatable) => {
+ inspectorAdapters.tables[name] = datatable;
+ },
...(execution.params as any).extraContext,
};
}
diff --git a/src/plugins/expressions/common/execution/execution_contract.test.ts b/src/plugins/expressions/common/execution/execution_contract.test.ts
index eaf7e6ea862eb..0a6704a8cb2f6 100644
--- a/src/plugins/expressions/common/execution/execution_contract.test.ts
+++ b/src/plugins/expressions/common/execution/execution_contract.test.ts
@@ -71,7 +71,7 @@ describe('ExecutionContract', () => {
const execution = createExecution('foo bar=123');
const contract = new ExecutionContract(execution);
expect(contract.inspect()).toMatchObject({
- data: expect.any(Object),
+ tables: expect.any(Object),
requests: expect.any(Object),
});
});
diff --git a/src/plugins/expressions/common/execution/types.ts b/src/plugins/expressions/common/execution/types.ts
index a41f97118c4b2..a1b25c3802f4b 100644
--- a/src/plugins/expressions/common/execution/types.ts
+++ b/src/plugins/expressions/common/execution/types.ts
@@ -21,8 +21,9 @@
import type { KibanaRequest } from 'src/core/server';
import { ExpressionType, SerializableState } from '../expression_types';
-import { Adapters, DataAdapter, RequestAdapter } from '../../../inspector/common';
+import { Adapters, RequestAdapter } from '../../../inspector/common';
import { SavedObject, SavedObjectAttributes } from '../../../../core/public';
+import { TablesAdapter } from '../util/tables_adapter';
/**
* `ExecutionContext` is an object available to all functions during a single execution;
@@ -89,5 +90,5 @@ export interface ExecutionContext<
*/
export interface DefaultInspectorAdapters extends Adapters {
requests: RequestAdapter;
- data: DataAdapter;
+ tables: TablesAdapter;
}
diff --git a/src/plugins/expressions/common/expression_renderers/types.ts b/src/plugins/expressions/common/expression_renderers/types.ts
index 88aca4c07ee31..fca1694747ce2 100644
--- a/src/plugins/expressions/common/expression_renderers/types.ts
+++ b/src/plugins/expressions/common/expression_renderers/types.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import { PersistedState } from 'src/plugins/visualizations/public';
-
export interface ExpressionRenderDefinition {
/**
* Technical name of the renderer, used as ID to identify renderer in
@@ -84,5 +82,10 @@ export interface IInterpreterRenderHandlers {
event: (event: any) => void;
hasCompatibleActions?: (event: any) => Promise;
getRenderMode: () => RenderMode;
- uiState?: PersistedState;
+ /**
+ * This uiState interface is actually `PersistedState` from the visualizations plugin,
+ * but expressions cannot know about vis or it creates a mess of circular dependencies.
+ * Downstream consumers of the uiState handler will need to cast for now.
+ */
+ uiState?: unknown;
}
diff --git a/src/plugins/expressions/common/util/index.ts b/src/plugins/expressions/common/util/index.ts
index ee677d54ce968..ea900687650f8 100644
--- a/src/plugins/expressions/common/util/index.ts
+++ b/src/plugins/expressions/common/util/index.ts
@@ -19,3 +19,4 @@
export * from './create_error';
export * from './get_by_alias';
+export * from './tables_adapter';
diff --git a/test/functional/apps/getting_started/index.js b/src/plugins/expressions/common/util/tables_adapter.ts
similarity index 66%
rename from test/functional/apps/getting_started/index.js
rename to src/plugins/expressions/common/util/tables_adapter.ts
index 399d3fe87484b..30b869818f999 100644
--- a/test/functional/apps/getting_started/index.js
+++ b/src/plugins/expressions/common/util/tables_adapter.ts
@@ -17,16 +17,18 @@
* under the License.
*/
-export default function ({ getService, loadTestFile }) {
- const browser = getService('browser');
+import { EventEmitter } from 'events';
+import { Datatable } from '../expression_types/specs';
- describe('Getting Started ', function () {
- this.tags(['ciGroup6']);
+export class TablesAdapter extends EventEmitter {
+ private _tables: { [key: string]: Datatable } = {};
- before(async function () {
- await browser.setWindowSize(1200, 800);
- });
- // https://www.elastic.co/guide/en/kibana/current/tutorial-load-dataset.html
- loadTestFile(require.resolve('./_shakespeare'));
- });
+ public logDatatable(name: string, datatable: Datatable): void {
+ this._tables[name] = datatable;
+ this.emit('change', this.tables);
+ }
+
+ public get tables() {
+ return this._tables;
+ }
}
diff --git a/src/plugins/expressions/public/index.ts b/src/plugins/expressions/public/index.ts
index 385055bc2fdc2..cd43c90d5ff45 100644
--- a/src/plugins/expressions/public/index.ts
+++ b/src/plugins/expressions/public/index.ts
@@ -117,4 +117,5 @@ export {
ExpressionsService,
ExpressionsServiceSetup,
ExpressionsServiceStart,
+ TablesAdapter,
} from '../common';
diff --git a/src/plugins/expressions/public/loader.test.ts b/src/plugins/expressions/public/loader.test.ts
index 598b614a326a9..0508b36fad385 100644
--- a/src/plugins/expressions/public/loader.test.ts
+++ b/src/plugins/expressions/public/loader.test.ts
@@ -166,7 +166,7 @@ describe('ExpressionLoader', () => {
it('inspect() returns correct inspector adapters', () => {
const expressionDataHandler = new ExpressionLoader(element, expressionString, {});
- expect(expressionDataHandler.inspect()).toHaveProperty('data');
+ expect(expressionDataHandler.inspect()).toHaveProperty('tables');
expect(expressionDataHandler.inspect()).toHaveProperty('requests');
});
});
diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md
index 6eb0e71c58e3f..404df2db019a1 100644
--- a/src/plugins/expressions/public/public.api.md
+++ b/src/plugins/expressions/public/public.api.md
@@ -12,7 +12,6 @@ import { EventEmitter } from 'events';
import { KibanaRequest } from 'src/core/server';
import { Observable } from 'rxjs';
import { PackageInfo } from '@kbn/config';
-import { PersistedState } from 'src/plugins/visualizations/public';
import { Plugin as Plugin_2 } from 'src/core/public';
import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public';
import React from 'react';
@@ -924,8 +923,7 @@ export interface IInterpreterRenderHandlers {
onDestroy: (fn: () => void) => void;
// (undocumented)
reload: () => void;
- // (undocumented)
- uiState?: PersistedState;
+ uiState?: unknown;
// (undocumented)
update: (params: any) => void;
}
@@ -1096,6 +1094,18 @@ export interface SerializedFieldFormat> {
// @public (undocumented)
export type Style = ExpressionTypeStyle;
+// Warning: (ae-missing-release-tag) "TablesAdapter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export class TablesAdapter extends EventEmitter {
+ // (undocumented)
+ logDatatable(name: string, datatable: Datatable): void;
+ // (undocumented)
+ get tables(): {
+ [key: string]: Datatable;
+ };
+ }
+
// Warning: (ae-missing-release-tag) "TextAlignment" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
diff --git a/src/plugins/expressions/public/react_expression_renderer.test.tsx b/src/plugins/expressions/public/react_expression_renderer.test.tsx
index e52d4d153882f..4ebd626e70fc3 100644
--- a/src/plugins/expressions/public/react_expression_renderer.test.tsx
+++ b/src/plugins/expressions/public/react_expression_renderer.test.tsx
@@ -146,6 +146,44 @@ describe('ExpressionRenderer', () => {
instance.unmount();
});
+ it('waits for debounce period on other loader option change if specified', () => {
+ jest.useFakeTimers();
+
+ const refreshSubject = new Subject();
+ const loaderUpdate = jest.fn();
+
+ (ExpressionLoader as jest.Mock).mockImplementation(() => {
+ return {
+ render$: new Subject(),
+ data$: new Subject(),
+ loading$: new Subject(),
+ update: loaderUpdate,
+ destroy: jest.fn(),
+ };
+ });
+
+ const instance = mount(
+
+ );
+
+ instance.setProps({ searchContext: { from: 'now-30m', to: 'now' } });
+
+ expect(loaderUpdate).toHaveBeenCalledTimes(1);
+
+ act(() => {
+ jest.runAllTimers();
+ });
+
+ expect(loaderUpdate).toHaveBeenCalledTimes(2);
+
+ instance.unmount();
+ });
+
it('should display a custom error message if the user provides one and then remove it after successful render', () => {
const dataSubject = new Subject();
const data$ = dataSubject.asObservable().pipe(share());
diff --git a/src/plugins/expressions/public/react_expression_renderer.tsx b/src/plugins/expressions/public/react_expression_renderer.tsx
index 894325c8b65f7..eac2371ec66d0 100644
--- a/src/plugins/expressions/public/react_expression_renderer.tsx
+++ b/src/plugins/expressions/public/react_expression_renderer.tsx
@@ -90,21 +90,23 @@ export const ReactExpressionRenderer = ({
null
);
const [debouncedExpression, setDebouncedExpression] = useState(expression);
- useEffect(() => {
+ const [waitingForDebounceToComplete, setDebouncePending] = useState(false);
+ useShallowCompareEffect(() => {
if (debounce === undefined) {
return;
}
+ setDebouncePending(true);
const handler = setTimeout(() => {
setDebouncedExpression(expression);
+ setDebouncePending(false);
}, debounce);
return () => {
clearTimeout(handler);
};
- }, [expression, debounce]);
+ }, [expression, expressionLoaderOptions, debounce]);
const activeExpression = debounce !== undefined ? debouncedExpression : expression;
- const waitingForDebounceToComplete = debounce !== undefined && expression !== debouncedExpression;
/* eslint-disable react-hooks/exhaustive-deps */
// OK to ignore react-hooks/exhaustive-deps because options update is handled by calling .update()
@@ -182,12 +184,16 @@ export const ReactExpressionRenderer = ({
// Re-fetch data automatically when the inputs change
useShallowCompareEffect(
() => {
- if (expressionLoaderRef.current) {
+ // only update the loader if the debounce period is over
+ if (expressionLoaderRef.current && !waitingForDebounceToComplete) {
expressionLoaderRef.current.update(activeExpression, expressionLoaderOptions);
}
},
- // when expression is changed by reference and when any other loaderOption is changed by reference
- [{ activeExpression, ...expressionLoaderOptions }]
+ // when debounced, wait for debounce status to change to update loader.
+ // Otherwise, update when expression is changed by reference and when any other loaderOption is changed by reference
+ debounce === undefined
+ ? [{ activeExpression, ...expressionLoaderOptions }]
+ : [{ waitingForDebounceToComplete }]
);
/* eslint-enable react-hooks/exhaustive-deps */
diff --git a/src/plugins/expressions/server/server.api.md b/src/plugins/expressions/server/server.api.md
index 7c1ab11f75027..8b8678371dd83 100644
--- a/src/plugins/expressions/server/server.api.md
+++ b/src/plugins/expressions/server/server.api.md
@@ -10,7 +10,6 @@ import { Ensure } from '@kbn/utility-types';
import { EventEmitter } from 'events';
import { KibanaRequest } from 'src/core/server';
import { Observable } from 'rxjs';
-import { PersistedState } from 'src/plugins/visualizations/public';
import { Plugin as Plugin_2 } from 'src/core/server';
import { PluginInitializerContext } from 'src/core/server';
import { UnwrapPromiseOrReturn } from '@kbn/utility-types';
@@ -741,8 +740,7 @@ export interface IInterpreterRenderHandlers {
onDestroy: (fn: () => void) => void;
// (undocumented)
reload: () => void;
- // (undocumented)
- uiState?: PersistedState;
+ uiState?: unknown;
// (undocumented)
update: (params: any) => void;
}
diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts
index 60d05890028d1..5cb837f816ff2 100644
--- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts
+++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts
@@ -34,7 +34,7 @@ export const getSavedObjects = (): SavedObject[] => [
defaultMessage: '[eCommerce] Sales by Category',
}),
visState:
- '{"title":"[eCommerce] Sales by Category","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Sum of total_quantity"}}],"seriesParams":[{"show":"true","type":"area","mode":"stacked","data":{"label":"Sum of total_quantity","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"top","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"sum","schema":"metric","params":{"field":"total_quantity"}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"order_date","interval":"auto","time_zone":"America/New_York","drop_partials":false,"customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"category.keyword","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
+ '{"title":"[eCommerce] Sales by Category","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Sum of total_quantity"}}],"seriesParams":[{"show":"true","type":"area","mode":"stacked","data":{"label":"Sum of total_quantity","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"top","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"sum","schema":"metric","params":{"field":"total_quantity"}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"order_date","interval":"auto","drop_partials":false,"min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"category.keyword","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
diff --git a/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts
index e65b6ad40651b..6b06a526a1239 100644
--- a/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts
+++ b/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts
@@ -56,7 +56,7 @@ export const getSavedObjects = (): SavedObject[] => [
defaultMessage: '[Flights] Flight Count and Average Ticket Price',
}),
visState:
- '{"title":"[Flights] Flight Count and Average Ticket Price","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Average Ticket Price"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Flight Count"}}],"seriesParams":[{"show":true,"mode":"stacked","type":"area","drawLinesBetweenPoints":true,"showCircles":false,"interpolate":"linear","lineWidth":2,"data":{"id":"5","label":"Flight Count"},"valueAxis":"ValueAxis-2"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"4","label":"Average Ticket Price"},"valueAxis":"ValueAxis-1","lineWidth":2}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":13},"aggs":[{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"5","enabled":true,"type":"count","schema":"metric","params":{"customLabel":"Flight Count"}},{"id":"4","enabled":true,"type":"avg","schema":"metric","params":{"field":"AvgTicketPrice","customLabel":"Average Ticket Price"}},{"id":"2","enabled":true,"type":"avg","schema":"radius","params":{"field":"AvgTicketPrice"}}]}',
+ '{"title":"[Flights] Flight Count and Average Ticket Price","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Average Ticket Price"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Flight Count"}}],"seriesParams":[{"show":true,"mode":"stacked","type":"area","drawLinesBetweenPoints":true,"showCircles":false,"interpolate":"linear","lineWidth":2,"data":{"id":"5","label":"Flight Count"},"valueAxis":"ValueAxis-2"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"4","label":"Average Ticket Price"},"valueAxis":"ValueAxis-1","lineWidth":2}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":13,"detailedTooltip":true},"aggs":[{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"5","enabled":true,"type":"count","schema":"metric","params":{"customLabel":"Flight Count"}},{"id":"4","enabled":true,"type":"avg","schema":"metric","params":{"field":"AvgTicketPrice","customLabel":"Average Ticket Price"}},{"id":"2","enabled":true,"type":"avg","schema":"radius","params":{"field":"AvgTicketPrice"}}]}',
uiStateJSON:
'{"vis":{"legendOpen":true,"colors":{"Average Ticket Price":"#629E51","Flight Count":"#AEA2E0"}}}',
description: '',
@@ -133,7 +133,7 @@ export const getSavedObjects = (): SavedObject[] => [
defaultMessage: '[Flights] Delay Type',
}),
visState:
- '{"title":"[Flights] Delay Type","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"cardinal","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"FlightDelayType","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
+ '{"title":"[Flights] Delay Type","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"cardinal","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"FlightDelayType","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
@@ -176,7 +176,7 @@ export const getSavedObjects = (): SavedObject[] => [
defaultMessage: '[Flights] Delay Buckets',
}),
visState:
- '{"title":"[Flights] Delay Buckets","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"histogram","schema":"segment","params":{"field":"FlightDelayMin","interval":30,"extended_bounds":{},"customLabel":"Flight Delay Minutes"}}]}',
+ '{"title":"[Flights] Delay Buckets","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"histogram","schema":"segment","params":{"field":"FlightDelayMin","interval":30,"extended_bounds":{},"customLabel":"Flight Delay Minutes"}}]}',
uiStateJSON: '{"vis":{"legendOpen":false}}',
description: '',
version: 1,
@@ -198,7 +198,7 @@ export const getSavedObjects = (): SavedObject[] => [
defaultMessage: '[Flights] Flight Delays',
}),
visState:
- '{"title":"[Flights] Flight Delays","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"FlightDelay","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Delays"}}]}',
+ '{"title":"[Flights] Flight Delays","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"FlightDelay","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Delays"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
@@ -220,7 +220,7 @@ export const getSavedObjects = (): SavedObject[] => [
defaultMessage: '[Flights] Flight Cancellations',
}),
visState:
- '{"title":"[Flights] Flight Cancellations","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"Cancelled","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Cancellations"}}]}',
+ '{"title":"[Flights] Flight Cancellations","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"left","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"BottomAxis-1","type":"value","position":"bottom","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"Cancelled","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Flight Cancellations"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts
index 068ba66c4b0de..7b891107cdfb0 100644
--- a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts
+++ b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts
@@ -33,7 +33,7 @@ export const getSavedObjects = (): SavedObject[] => [
defaultMessage: '[Logs] Unique Visitors vs. Average Bytes',
}),
visState:
- '{"title":"[Logs] Unique Visitors vs. Average Bytes","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Avg. Bytes"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Unique Visitors"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Avg. Bytes","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"2","label":"Unique Visitors"},"valueAxis":"ValueAxis-2"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":17},"aggs":[{"id":"1","enabled":true,"type":"avg","schema":"metric","params":{"field":"bytes","customLabel":"Avg. Bytes"}},{"id":"2","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"clientip","customLabel":"Unique Visitors"}},{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","time_zone":"America/Los_Angeles","customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"4","enabled":true,"type":"count","schema":"radius","params":{}}]}',
+ '{"title":"[Logs] Unique Visitors vs. Average Bytes","type":"area","params":{"type":"area","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"filter":true},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Avg. Bytes"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Unique Visitors"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Avg. Bytes","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"linear","valueAxis":"ValueAxis-1"},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"2","label":"Unique Visitors"},"valueAxis":"ValueAxis-2"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":17,"detailedTooltip":true},"aggs":[{"id":"1","enabled":true,"type":"avg","schema":"metric","params":{"field":"bytes","customLabel":"Avg. Bytes"}},{"id":"2","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"clientip","customLabel":"Unique Visitors"}},{"id":"3","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","interval":"auto","min_doc_count":1,"extended_bounds":{}}},{"id":"4","enabled":true,"type":"count","schema":"radius","params":{}}]}',
uiStateJSON: '{"vis":{"colors":{"Avg. Bytes":"#70DBED","Unique Visitors":"#0A437C"}}}',
description: '',
version: 1,
diff --git a/src/plugins/inspector/common/adapters/data/data_adapters.test.ts b/src/plugins/inspector/common/adapters/data/data_adapters.test.ts
deleted file mode 100644
index 7cc52807548f0..0000000000000
--- a/src/plugins/inspector/common/adapters/data/data_adapters.test.ts
+++ /dev/null
@@ -1,71 +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 { DataAdapter } from './data_adapter';
-
-describe('DataAdapter', () => {
- let adapter: DataAdapter;
-
- beforeEach(() => {
- adapter = new DataAdapter();
- });
-
- describe('getTabular()', () => {
- it('should return a null promise when called before initialized', () => {
- expect(adapter.getTabular()).resolves.toEqual({
- data: null,
- options: {},
- });
- });
-
- it('should call the provided callback and resolve with its value', async () => {
- const data = { columns: [], rows: [] };
- const spy = jest.fn(() => data);
- adapter.setTabularLoader(spy);
- expect(spy).not.toBeCalled();
- const result = await adapter.getTabular();
- expect(spy).toBeCalled();
- expect(result.data).toBe(data);
- });
-
- it('should pass through options specified via setTabularLoader', async () => {
- const data = { columns: [], rows: [] };
- adapter.setTabularLoader(() => data, { returnsFormattedValues: true });
- const result = await adapter.getTabular();
- expect(result.options).toEqual({ returnsFormattedValues: true });
- });
-
- it('should return options set when starting loading data', async () => {
- const data = { columns: [], rows: [] };
- adapter.setTabularLoader(() => data, { returnsFormattedValues: true });
- const waitForResult = adapter.getTabular();
- adapter.setTabularLoader(() => data, { returnsFormattedValues: false });
- const result = await waitForResult;
- expect(result.options).toEqual({ returnsFormattedValues: true });
- });
- });
-
- it('should emit a "tabular" event when a new tabular loader is specified', () => {
- const data = { columns: [], rows: [] };
- const spy = jest.fn();
- adapter.once('change', spy);
- adapter.setTabularLoader(() => data);
- expect(spy).toBeCalled();
- });
-});
diff --git a/src/plugins/inspector/common/adapters/index.ts b/src/plugins/inspector/common/adapters/index.ts
index 0c6319a2905a8..152d7c54d7d84 100644
--- a/src/plugins/inspector/common/adapters/index.ts
+++ b/src/plugins/inspector/common/adapters/index.ts
@@ -17,6 +17,5 @@
* under the License.
*/
-export * from './data';
export * from './request';
export * from './types';
diff --git a/src/plugins/inspector/common/adapters/types.ts b/src/plugins/inspector/common/adapters/types.ts
index b51c3e56c749f..ee56c994be469 100644
--- a/src/plugins/inspector/common/adapters/types.ts
+++ b/src/plugins/inspector/common/adapters/types.ts
@@ -17,14 +17,12 @@
* under the License.
*/
-import type { DataAdapter } from './data';
import type { RequestAdapter } from './request';
/**
* The interface that the adapters used to open an inspector have to fullfill.
*/
export interface Adapters {
- data?: DataAdapter;
requests?: RequestAdapter;
[key: string]: any;
}
diff --git a/src/plugins/inspector/common/index.ts b/src/plugins/inspector/common/index.ts
index c5755b22095dc..f9f486521a76b 100644
--- a/src/plugins/inspector/common/index.ts
+++ b/src/plugins/inspector/common/index.ts
@@ -19,15 +19,9 @@
export {
Adapters,
- DataAdapter,
- FormattedData,
RequestAdapter,
RequestStatistic,
RequestStatistics,
RequestStatus,
RequestResponder,
- TabularData,
- TabularDataColumn,
- TabularDataRow,
- TabularDataValue,
} from './adapters';
diff --git a/src/plugins/inspector/public/plugin.tsx b/src/plugins/inspector/public/plugin.tsx
index 07ef7c8fbab0d..d3d867344a2a8 100644
--- a/src/plugins/inspector/public/plugin.tsx
+++ b/src/plugins/inspector/public/plugin.tsx
@@ -26,7 +26,7 @@ import { InspectorOptions, InspectorSession } from './types';
import { InspectorPanel } from './ui/inspector_panel';
import { Adapters } from '../common';
-import { getRequestsViewDescription, getDataViewDescription } from './views';
+import { getRequestsViewDescription } from './views';
export interface Setup {
registerView: InspectorViewRegistry['register'];
@@ -70,7 +70,6 @@ export class InspectorPublicPlugin implements Plugin {
public async setup(core: CoreSetup) {
this.views = new InspectorViewRegistry();
- this.views.register(getDataViewDescription());
this.views.register(getRequestsViewDescription());
return {
diff --git a/src/plugins/inspector/public/test/is_available.test.ts b/src/plugins/inspector/public/test/is_available.test.ts
index c38d9d7a3f825..1f5220fc07a63 100644
--- a/src/plugins/inspector/public/test/is_available.test.ts
+++ b/src/plugins/inspector/public/test/is_available.test.ts
@@ -18,19 +18,12 @@
*/
import { inspectorPluginMock } from '../mocks';
-import { DataAdapter, RequestAdapter } from '../../common/adapters';
+import { RequestAdapter } from '../../common/adapters';
-const adapter1 = new DataAdapter();
const adapter2 = new RequestAdapter();
describe('inspector', () => {
describe('isAvailable()', () => {
- it('should return false if no view would be available', async () => {
- const { doStart } = await inspectorPluginMock.createPlugin();
- const start = await doStart();
- expect(start.isAvailable({ adapter1 })).toBe(false);
- });
-
it('should return true if views would be available, false otherwise', async () => {
const { setup, doStart } = await inspectorPluginMock.createPlugin();
@@ -44,7 +37,6 @@ describe('inspector', () => {
const start = await doStart();
- expect(start.isAvailable({ adapter1 })).toBe(true);
expect(start.isAvailable({ adapter2 })).toBe(false);
});
});
diff --git a/src/plugins/inspector/public/views/_index.scss b/src/plugins/inspector/public/views/_index.scss
index 620a33e965840..43fbc09e921cc 100644
--- a/src/plugins/inspector/public/views/_index.scss
+++ b/src/plugins/inspector/public/views/_index.scss
@@ -1,2 +1 @@
-@import './data/index';
@import './requests/index';
diff --git a/src/plugins/inspector/public/views/data/components/data_view.tsx b/src/plugins/inspector/public/views/data/components/data_view.tsx
deleted file mode 100644
index 324094d8f93d0..0000000000000
--- a/src/plugins/inspector/public/views/data/components/data_view.tsx
+++ /dev/null
@@ -1,187 +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 React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { FormattedMessage } from '@kbn/i18n/react';
-import {
- EuiEmptyPrompt,
- EuiFlexGroup,
- EuiFlexItem,
- EuiLoadingChart,
- EuiPanel,
- EuiSpacer,
- EuiText,
-} from '@elastic/eui';
-
-import { DataTableFormat } from './data_table';
-import { InspectorViewProps } from '../../../types';
-import { Adapters } from '../../../../common';
-import {
- TabularLoaderOptions,
- TabularData,
- TabularHolder,
-} from '../../../../common/adapters/data/types';
-import { IUiSettingsClient } from '../../../../../../core/public';
-import { withKibana, KibanaReactContextValue } from '../../../../../kibana_react/public';
-
-interface DataViewComponentState {
- tabularData: TabularData | null;
- tabularOptions: TabularLoaderOptions;
- adapters: Adapters;
- tabularPromise: Promise | null;
-}
-
-interface DataViewComponentProps extends InspectorViewProps {
- kibana: KibanaReactContextValue<{ uiSettings: IUiSettingsClient }>;
-}
-
-class DataViewComponent extends Component {
- static propTypes = {
- adapters: PropTypes.object.isRequired,
- title: PropTypes.string.isRequired,
- kibana: PropTypes.object,
- };
-
- state = {} as DataViewComponentState;
- _isMounted = false;
-
- static getDerivedStateFromProps(
- nextProps: DataViewComponentProps,
- state: DataViewComponentState
- ) {
- if (state && nextProps.adapters === state.adapters) {
- return null;
- }
-
- return {
- adapters: nextProps.adapters,
- tabularData: null,
- tabularOptions: {},
- tabularPromise: nextProps.adapters.data!.getTabular(),
- };
- }
-
- onUpdateData = (type: string) => {
- if (type === 'tabular') {
- this.setState({
- tabularData: null,
- tabularOptions: {},
- tabularPromise: this.props.adapters.data!.getTabular(),
- });
- }
- };
-
- async finishLoadingData() {
- const { tabularPromise } = this.state;
-
- if (tabularPromise) {
- const tabularData: TabularHolder = await tabularPromise;
-
- if (this._isMounted) {
- this.setState({
- tabularData: tabularData.data,
- tabularOptions: tabularData.options,
- tabularPromise: null,
- });
- }
- }
- }
-
- componentDidMount() {
- this._isMounted = true;
- this.props.adapters.data!.on('change', this.onUpdateData);
- this.finishLoadingData();
- }
-
- componentWillUnmount() {
- this._isMounted = false;
- this.props.adapters.data!.removeListener('change', this.onUpdateData);
- }
-
- componentDidUpdate() {
- this.finishLoadingData();
- }
-
- static renderNoData() {
- return (
-
-
-
- }
- body={
-
-
-
-
-
- }
- />
- );
- }
-
- static renderLoading() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-
- render() {
- if (this.state.tabularPromise) {
- return DataViewComponent.renderLoading();
- } else if (!this.state.tabularData) {
- return DataViewComponent.renderNoData();
- }
-
- return (
-
- );
- }
-}
-
-// default export required for React.Lazy
-// eslint-disable-next-line import/no-default-export
-export default withKibana(DataViewComponent);
diff --git a/src/plugins/inspector/public/views/index.ts b/src/plugins/inspector/public/views/index.ts
index c75ecfbd3e998..8aef30a68a327 100644
--- a/src/plugins/inspector/public/views/index.ts
+++ b/src/plugins/inspector/public/views/index.ts
@@ -17,5 +17,4 @@
* under the License.
*/
-export { getDataViewDescription } from './data';
export { getRequestsViewDescription } from './requests';
diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.test.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.test.ts
index a7681e1766427..64f1088dc3392 100644
--- a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.test.ts
+++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.test.ts
@@ -16,14 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks';
import { getSavedObjectsCounts } from './get_saved_object_counts';
+export function mockGetSavedObjectsCounts(params: any) {
+ const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
+ esClient.search.mockResolvedValue(
+ // @ts-ignore we only care about the response body
+ {
+ body: { ...params },
+ }
+ );
+ return esClient;
+}
+
describe('getSavedObjectsCounts', () => {
test('Get all the saved objects equal to 0 because no results were found', async () => {
- const callCluster = jest.fn(() => ({}));
+ const esClient = mockGetSavedObjectsCounts({});
- const results = await getSavedObjectsCounts(callCluster as any, '.kibana');
+ const results = await getSavedObjectsCounts(esClient, '.kibana');
expect(results).toStrictEqual({
dashboard: { total: 0 },
visualization: { total: 0 },
@@ -35,7 +46,7 @@ describe('getSavedObjectsCounts', () => {
});
test('Merge the zeros with the results', async () => {
- const callCluster = jest.fn(() => ({
+ const esClient = mockGetSavedObjectsCounts({
aggregations: {
types: {
buckets: [
@@ -46,9 +57,9 @@ describe('getSavedObjectsCounts', () => {
],
},
},
- }));
+ });
- const results = await getSavedObjectsCounts(callCluster as any, '.kibana');
+ const results = await getSavedObjectsCounts(esClient, '.kibana');
expect(results).toStrictEqual({
dashboard: { total: 1 },
visualization: { total: 0 },
diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts
index e88d90fe5b24b..65cc3643a88cb 100644
--- a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts
+++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts
@@ -27,7 +27,7 @@
*/
import { snakeCase } from 'lodash';
-import { LegacyAPICaller } from 'kibana/server';
+import { ElasticsearchClient } from 'src/core/server';
const TYPES = [
'dashboard',
@@ -48,7 +48,7 @@ export interface KibanaSavedObjectCounts {
}
export async function getSavedObjectsCounts(
- callCluster: LegacyAPICaller,
+ esClient: ElasticsearchClient,
kibanaIndex: string // Typically '.kibana'. We might need a way to obtain it from the SavedObjects client (or the SavedObjects client to provide a way to run aggregations?)
): Promise {
const savedObjectCountSearchParams = {
@@ -67,9 +67,9 @@ export async function getSavedObjectsCounts(
},
},
};
- const resp = await callCluster('search', savedObjectCountSearchParams);
+ const { body } = await esClient.search(savedObjectCountSearchParams);
const buckets: Array<{ key: string; doc_count: number }> =
- resp.aggregations?.types?.buckets || [];
+ body.aggregations?.types?.buckets || [];
// Initialise the object with all zeros for all the types
const allZeros: KibanaSavedObjectCounts = TYPES.reduce(
diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/index.test.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/index.test.ts
index 83cac1d456a3a..dee9ca4d32c5f 100644
--- a/src/plugins/kibana_usage_collection/server/collectors/kibana/index.test.ts
+++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/index.test.ts
@@ -20,12 +20,13 @@
import {
loggingSystemMock,
pluginInitializerContextConfigMock,
+ elasticsearchServiceMock,
} from '../../../../../core/server/mocks';
import {
Collector,
+ createCollectorFetchContextMock,
createUsageCollectionSetupMock,
} from '../../../../usage_collection/server/usage_collection.mock';
-import { createCollectorFetchContextMock } from '../../../../usage_collection/server/mocks';
import { registerKibanaUsageCollector } from './';
const logger = loggingSystemMock.createLogger();
@@ -43,7 +44,9 @@ describe('telemetry_kibana', () => {
const getMockFetchClients = (hits?: unknown[]) => {
const fetchParamsMock = createCollectorFetchContextMock();
- fetchParamsMock.callCluster.mockResolvedValue({ hits: { hits } });
+ const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
+ esClient.search.mockResolvedValue({ body: { hits: { hits } } } as any);
+ fetchParamsMock.esClient = esClient;
return fetchParamsMock;
};
diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts
index 6c2e0a2c926ad..5dd39d172e1c2 100644
--- a/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts
+++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts
@@ -43,13 +43,13 @@ export function getKibanaUsageCollector(
graph_workspace: { total: { type: 'long' } },
timelion_sheet: { total: { type: 'long' } },
},
- async fetch({ callCluster }) {
+ async fetch({ esClient }) {
const {
kibana: { index },
} = await legacyConfig$.pipe(take(1)).toPromise();
return {
index,
- ...(await getSavedObjectsCounts(callCluster, index)),
+ ...(await getSavedObjectsCounts(esClient, index)),
};
},
});
diff --git a/src/plugins/kibana_utils/server/index.ts b/src/plugins/kibana_utils/server/index.ts
index d994a4940bdfd..a0e933f997dd5 100644
--- a/src/plugins/kibana_utils/server/index.ts
+++ b/src/plugins/kibana_utils/server/index.ts
@@ -28,3 +28,5 @@ export {
Set,
url,
} from '../common';
+
+export { KbnServerError, reportServerError } from './report_server_error';
diff --git a/src/plugins/kibana_utils/server/report_server_error.ts b/src/plugins/kibana_utils/server/report_server_error.ts
new file mode 100644
index 0000000000000..43b4dba3d039b
--- /dev/null
+++ b/src/plugins/kibana_utils/server/report_server_error.ts
@@ -0,0 +1,39 @@
+/*
+ * 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 { KibanaResponseFactory } from 'kibana/server';
+import { KbnError } from '../common';
+
+export class KbnServerError extends KbnError {
+ constructor(message: string, public readonly statusCode: number) {
+ super(message);
+ }
+}
+
+export function reportServerError(res: KibanaResponseFactory, err: any) {
+ return res.customError({
+ statusCode: err.statusCode ?? 500,
+ body: {
+ message: err.message,
+ attributes: {
+ error: err.body?.error || err.message,
+ },
+ },
+ });
+}
diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts
index bf03c649fa6b4..81026927380e0 100644
--- a/src/plugins/management/public/plugin.ts
+++ b/src/plugins/management/public/plugin.ts
@@ -58,11 +58,12 @@ export class ManagementPlugin implements Plugin ({
default: '"{}"',
},
},
- fn(context, args) {
+ fn(context, args, handlers) {
const visConfig = JSON.parse(args.visConfig);
+ if (handlers?.inspectorAdapters?.tables) {
+ handlers.inspectorAdapters.tables.logDatatable('default', context);
+ }
return {
type: 'render',
as: 'visualization',
diff --git a/src/plugins/region_map/public/region_map_fn.test.js b/src/plugins/region_map/public/region_map_fn.test.js
index 32467541dee02..d83d04be6d38c 100644
--- a/src/plugins/region_map/public/region_map_fn.test.js
+++ b/src/plugins/region_map/public/region_map_fn.test.js
@@ -57,7 +57,11 @@ describe('interpreter/functions#regionmap', () => {
};
it('returns an object with the correct structure', () => {
- const actual = fn(context, { visConfig: JSON.stringify(visConfig) });
+ const actual = fn(
+ context,
+ { visConfig: JSON.stringify(visConfig) },
+ { logDatatable: jest.fn() }
+ );
expect(actual).toMatchSnapshot();
});
});
diff --git a/src/plugins/telemetry/common/constants.ts b/src/plugins/telemetry/common/constants.ts
index fc77332c18fc9..2fa8b32f68291 100644
--- a/src/plugins/telemetry/common/constants.ts
+++ b/src/plugins/telemetry/common/constants.ts
@@ -49,7 +49,7 @@ export const LOCALSTORAGE_KEY = 'telemetry.data';
/**
* Link to Advanced Settings.
*/
-export const PATH_TO_ADVANCED_SETTINGS = 'management/kibana/settings';
+export const PATH_TO_ADVANCED_SETTINGS = '/app/management/kibana/settings';
/**
* Link to the Elastic Telemetry privacy statement.
diff --git a/src/plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap b/src/plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap
index 62998da73d6f9..897e3b2761c74 100644
--- a/src/plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap
+++ b/src/plugins/telemetry/public/components/__snapshots__/opted_in_notice_banner.test.tsx.snap
@@ -10,7 +10,7 @@ exports[`OptInDetailsComponent renders as expected 1`] = `
values={
Object {
"disableLink":
{
it('renders as expected', () => {
- expect(shallowWithIntl( {}} />)).toMatchSnapshot();
+ expect(
+ shallowWithIntl( {}} http={mockHttp} />)
+ ).toMatchSnapshot();
});
it('fires the "onSeenBanner" prop when a link is clicked', () => {
const onLinkClick = jest.fn();
- const component = shallowWithIntl();
+ const component = shallowWithIntl(
+
+ );
const button = component.findWhere((n) => n.type() === EuiButton);
diff --git a/src/plugins/telemetry/public/components/opted_in_notice_banner.tsx b/src/plugins/telemetry/public/components/opted_in_notice_banner.tsx
index 090893964c881..46ae17171203c 100644
--- a/src/plugins/telemetry/public/components/opted_in_notice_banner.tsx
+++ b/src/plugins/telemetry/public/components/opted_in_notice_banner.tsx
@@ -24,14 +24,18 @@ import { EuiButton, EuiLink, EuiCallOut, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { PATH_TO_ADVANCED_SETTINGS, PRIVACY_STATEMENT_URL } from '../../common/constants';
+import { HttpSetup } from '../../../../core/public';
interface Props {
+ http: HttpSetup;
onSeenBanner: () => any;
}
export class OptedInNoticeBanner extends React.PureComponent {
render() {
- const { onSeenBanner } = this.props;
+ const { onSeenBanner, http } = this.props;
+ const basePath = http.basePath.get();
+
const bannerTitle = i18n.translate('telemetry.telemetryOptedInNoticeTitle', {
defaultMessage: 'Help us improve the Elastic Stack',
});
@@ -56,7 +60,7 @@ export class OptedInNoticeBanner extends React.PureComponent {
),
disableLink: (
-
+
{
it('adds a banner to banners with priority of 10000', () => {
const bannerID = 'brucer-wayne';
const overlays = overlayServiceMock.createStartContract();
+ const mockHttp = httpServiceMock.createStartContract();
overlays.banners.add.mockReturnValue(bannerID);
const returnedBannerId = renderOptedInNoticeBanner({
+ http: mockHttp,
onSeen: jest.fn(),
overlays,
});
diff --git a/src/plugins/telemetry/public/services/telemetry_notifications/render_opted_in_notice_banner.tsx b/src/plugins/telemetry/public/services/telemetry_notifications/render_opted_in_notice_banner.tsx
index e63e46af6e8ca..e1feea4b6cbe1 100644
--- a/src/plugins/telemetry/public/services/telemetry_notifications/render_opted_in_notice_banner.tsx
+++ b/src/plugins/telemetry/public/services/telemetry_notifications/render_opted_in_notice_banner.tsx
@@ -23,11 +23,12 @@ import { OptedInNoticeBanner } from '../../components/opted_in_notice_banner';
import { toMountPoint } from '../../../../kibana_react/public';
interface RenderBannerConfig {
+ http: CoreStart['http'];
overlays: CoreStart['overlays'];
onSeen: () => void;
}
-export function renderOptedInNoticeBanner({ onSeen, overlays }: RenderBannerConfig) {
- const mount = toMountPoint();
+export function renderOptedInNoticeBanner({ onSeen, overlays, http }: RenderBannerConfig) {
+ const mount = toMountPoint();
const bannerId = overlays.banners.add(mount, 10000);
return bannerId;
diff --git a/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts b/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts
index fc44a4db7cf5e..6ebbfcfb91336 100644
--- a/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts
+++ b/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts
@@ -23,18 +23,21 @@ import { renderOptInBanner } from './render_opt_in_banner';
import { TelemetryService } from '../telemetry_service';
interface TelemetryNotificationsConstructor {
+ http: CoreStart['http'];
overlays: CoreStart['overlays'];
telemetryService: TelemetryService;
}
export class TelemetryNotifications {
+ private readonly http: CoreStart['http'];
private readonly overlays: CoreStart['overlays'];
private readonly telemetryService: TelemetryService;
private optedInNoticeBannerId?: string;
private optInBannerId?: string;
- constructor({ overlays, telemetryService }: TelemetryNotificationsConstructor) {
+ constructor({ http, overlays, telemetryService }: TelemetryNotificationsConstructor) {
this.telemetryService = telemetryService;
+ this.http = http;
this.overlays = overlays;
}
@@ -46,6 +49,7 @@ export class TelemetryNotifications {
public renderOptedInNoticeBanner = (): void => {
const bannerId = renderOptedInNoticeBanner({
+ http: this.http,
onSeen: this.setOptedInNoticeSeen,
overlays: this.overlays,
});
diff --git a/src/plugins/tile_map/public/tile_map_fn.js b/src/plugins/tile_map/public/tile_map_fn.js
index 3253598d98d94..7a5f36be1eb9d 100644
--- a/src/plugins/tile_map/public/tile_map_fn.js
+++ b/src/plugins/tile_map/public/tile_map_fn.js
@@ -34,7 +34,7 @@ export const createTileMapFn = () => ({
default: '"{}"',
},
},
- fn(context, args) {
+ fn(context, args, handlers) {
const visConfig = JSON.parse(args.visConfig);
const { geohash, metric, geocentroid } = visConfig.dimensions;
const convertedData = convertToGeoJson(context, {
@@ -47,6 +47,9 @@ export const createTileMapFn = () => ({
convertedData.meta.geohash = context.columns[geohash.accessor].meta;
}
+ if (handlers?.inspectorAdapters?.tables) {
+ handlers.inspectorAdapters.tables.logDatatable('default', context);
+ }
return {
type: 'render',
as: 'visualization',
diff --git a/src/plugins/tile_map/public/tilemap_fn.test.js b/src/plugins/tile_map/public/tilemap_fn.test.js
index df9fc10a7303c..895842ea1e8f4 100644
--- a/src/plugins/tile_map/public/tilemap_fn.test.js
+++ b/src/plugins/tile_map/public/tilemap_fn.test.js
@@ -80,13 +80,17 @@ describe('interpreter/functions#tilemap', () => {
});
it('returns an object with the correct structure', () => {
- const actual = fn(context, { visConfig: JSON.stringify(visConfig) });
+ const actual = fn(
+ context,
+ { visConfig: JSON.stringify(visConfig) },
+ { logDatatable: jest.fn() }
+ );
expect(actual).toMatchSnapshot();
});
it('calls response handler with correct values', () => {
const { geohash, metric, geocentroid } = visConfig.dimensions;
- fn(context, { visConfig: JSON.stringify(visConfig) });
+ fn(context, { visConfig: JSON.stringify(visConfig) }, { logDatatable: jest.fn() });
expect(convertToGeoJson).toHaveBeenCalledTimes(1);
expect(convertToGeoJson).toHaveBeenCalledWith(context, {
geohash,
diff --git a/src/plugins/ui_actions/public/index.ts b/src/plugins/ui_actions/public/index.ts
index d223c0abcccb7..7890e4bab44a3 100644
--- a/src/plugins/ui_actions/public/index.ts
+++ b/src/plugins/ui_actions/public/index.ts
@@ -40,12 +40,6 @@ export {
export {
Trigger,
TriggerContext,
- SELECT_RANGE_TRIGGER,
- selectRangeTrigger,
- VALUE_CLICK_TRIGGER,
- valueClickTrigger,
- APPLY_FILTER_TRIGGER,
- applyFilterTrigger,
VISUALIZE_FIELD_TRIGGER,
visualizeFieldTrigger,
VISUALIZE_GEO_FIELD_TRIGGER,
diff --git a/src/plugins/ui_actions/public/plugin.ts b/src/plugins/ui_actions/public/plugin.ts
index fdb75e9a426e9..84a7ae45fc7b8 100644
--- a/src/plugins/ui_actions/public/plugin.ts
+++ b/src/plugins/ui_actions/public/plugin.ts
@@ -20,14 +20,7 @@
import { CoreStart, CoreSetup, Plugin, PluginInitializerContext } from 'src/core/public';
import { PublicMethodsOf } from '@kbn/utility-types';
import { UiActionsService } from './service';
-import {
- selectRangeTrigger,
- valueClickTrigger,
- rowClickTrigger,
- applyFilterTrigger,
- visualizeFieldTrigger,
- visualizeGeoFieldTrigger,
-} from './triggers';
+import { rowClickTrigger, visualizeFieldTrigger, visualizeGeoFieldTrigger } from './triggers';
export type UiActionsSetup = Pick<
UiActionsService,
@@ -47,10 +40,7 @@ export class UiActionsPlugin implements Plugin {
constructor(initializerContext: PluginInitializerContext) {}
public setup(core: CoreSetup): UiActionsSetup {
- this.service.registerTrigger(selectRangeTrigger);
- this.service.registerTrigger(valueClickTrigger);
this.service.registerTrigger(rowClickTrigger);
- this.service.registerTrigger(applyFilterTrigger);
this.service.registerTrigger(visualizeFieldTrigger);
this.service.registerTrigger(visualizeGeoFieldTrigger);
return this.service;
diff --git a/src/plugins/ui_actions/public/public.api.md b/src/plugins/ui_actions/public/public.api.md
index 2384dfab13c8c..808cb1f3fbca0 100644
--- a/src/plugins/ui_actions/public/public.api.md
+++ b/src/plugins/ui_actions/public/public.api.md
@@ -8,14 +8,11 @@ import { CoreSetup } from 'src/core/public';
import { CoreStart } from 'src/core/public';
import { EnvironmentMode } from '@kbn/config';
import { EuiContextMenuPanelDescriptor } from '@elastic/eui';
-import { EventEmitter } from 'events';
-import { Observable } from 'rxjs';
import { PackageInfo } from '@kbn/config';
import { Plugin } from 'src/core/public';
import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public';
import { PublicMethodsOf } from '@kbn/utility-types';
import React from 'react';
-import * as Rx from 'rxjs';
import { UiComponent } from 'src/plugins/kibana_utils/public';
// Warning: (ae-forgotten-export) The symbol "BaseContext" needs to be exported by the entry point index.d.ts
@@ -95,16 +92,6 @@ export interface ActionExecutionMeta {
// @public (undocumented)
export type ActionType = keyof ActionContextMapping;
-// Warning: (ae-missing-release-tag) "APPLY_FILTER_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const APPLY_FILTER_TRIGGER = "FILTER_TRIGGER";
-
-// Warning: (ae-missing-release-tag) "applyFilterTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const applyFilterTrigger: Trigger<'FILTER_TRIGGER'>;
-
// Warning: (ae-forgotten-export) The symbol "BuildContextMenuParams" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "buildContextMenuForActions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -148,10 +135,8 @@ export interface RowClickContext {
table: Datatable;
columns?: string[];
};
- // Warning: (ae-forgotten-export) The symbol "IEmbeddable" needs to be exported by the entry point index.d.ts
- //
// (undocumented)
- embeddable?: IEmbeddable;
+ embeddable?: unknown;
}
// Warning: (ae-missing-release-tag) "rowClickTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -159,16 +144,6 @@ export interface RowClickContext {
// @public (undocumented)
export const rowClickTrigger: Trigger<'ROW_CLICK_TRIGGER'>;
-// Warning: (ae-missing-release-tag) "SELECT_RANGE_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const SELECT_RANGE_TRIGGER = "SELECT_RANGE_TRIGGER";
-
-// Warning: (ae-missing-release-tag) "selectRangeTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'>;
-
// Warning: (ae-missing-release-tag) "Trigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
@@ -192,20 +167,8 @@ export interface TriggerContextMapping {
//
// (undocumented)
[DEFAULT_TRIGGER]: TriggerContext_2;
- // Warning: (ae-forgotten-export) The symbol "ApplyGlobalFilterActionContext" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- [APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext;
// (undocumented)
[ROW_CLICK_TRIGGER]: RowClickContext;
- // Warning: (ae-forgotten-export) The symbol "RangeSelectContext" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- [SELECT_RANGE_TRIGGER]: RangeSelectContext;
- // Warning: (ae-forgotten-export) The symbol "ValueClickContext" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- [VALUE_CLICK_TRIGGER]: ValueClickContext;
// (undocumented)
[VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext;
// (undocumented)
@@ -262,35 +225,35 @@ export class UiActionsService {
//
// (undocumented)
protected readonly actions: ActionRegistry;
- readonly addTriggerAction: (triggerId: T, action: UiActionsActionDefinition | Action) => void;
+ readonly addTriggerAction: (triggerId: T, action: UiActionsActionDefinition | Action) => void;
// (undocumented)
- readonly attachAction: (triggerId: T, actionId: string) => void;
+ readonly attachAction: (triggerId: T, actionId: string) => void;
readonly clear: () => void;
// (undocumented)
readonly detachAction: (triggerId: TriggerId, actionId: string) => void;
// @deprecated (undocumented)
- readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise;
+ readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise;
// Warning: (ae-forgotten-export) The symbol "UiActionsExecutionService" needs to be exported by the entry point index.d.ts
//
// (undocumented)
readonly executionService: UiActionsExecutionService;
readonly fork: () => UiActionsService;
// (undocumented)
- readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">;
+ readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">;
// Warning: (ae-forgotten-export) The symbol "TriggerContract" needs to be exported by the entry point index.d.ts
//
// (undocumented)
- readonly getTrigger: (triggerId: T) => TriggerContract;
+ readonly getTrigger: (triggerId: T) => TriggerContract;
// (undocumented)
- readonly getTriggerActions: (triggerId: T) => Action[];
+ readonly getTriggerActions: (triggerId: T) => Action[];
// (undocumented)
- readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>;
+ readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>;
// (undocumented)
readonly hasAction: (actionId: string) => boolean;
// Warning: (ae-forgotten-export) The symbol "ActionContext" needs to be exported by the entry point index.d.ts
//
// (undocumented)
- readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_EXPORT_CSV">;
+ readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">;
// (undocumented)
readonly registerTrigger: (trigger: Trigger) => void;
// Warning: (ae-forgotten-export) The symbol "TriggerRegistry" needs to be exported by the entry point index.d.ts
@@ -326,16 +289,6 @@ export type UiActionsSetup = Pick;
-// Warning: (ae-missing-release-tag) "VALUE_CLICK_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const VALUE_CLICK_TRIGGER = "VALUE_CLICK_TRIGGER";
-
-// Warning: (ae-missing-release-tag) "valueClickTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'>;
-
// Warning: (ae-missing-release-tag) "VISUALIZE_FIELD_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -371,7 +324,7 @@ export const visualizeGeoFieldTrigger: Trigger<'VISUALIZE_GEO_FIELD_TRIGGER'>;
// Warnings were encountered during analysis:
//
-// src/plugins/ui_actions/public/triggers/row_click_trigger.ts:45:5 - (ae-forgotten-export) The symbol "Datatable" needs to be exported by the entry point index.d.ts
+// src/plugins/ui_actions/public/triggers/row_click_trigger.ts:46:5 - (ae-forgotten-export) The symbol "Datatable" needs to be exported by the entry point index.d.ts
// (No @packageDocumentation comment for this package)
diff --git a/src/plugins/ui_actions/public/triggers/index.ts b/src/plugins/ui_actions/public/triggers/index.ts
index ecbf4d1f7b988..6bba87e85eb95 100644
--- a/src/plugins/ui_actions/public/triggers/index.ts
+++ b/src/plugins/ui_actions/public/triggers/index.ts
@@ -20,10 +20,7 @@
export * from './trigger';
export * from './trigger_contract';
export * from './trigger_internal';
-export * from './select_range_trigger';
-export * from './value_click_trigger';
export * from './row_click_trigger';
-export * from './apply_filter_trigger';
export * from './visualize_field_trigger';
export * from './visualize_geo_field_trigger';
export * from './default_trigger';
diff --git a/src/plugins/ui_actions/public/triggers/row_click_trigger.ts b/src/plugins/ui_actions/public/triggers/row_click_trigger.ts
index 87bca03f8c3ba..0fc261b3e1fb3 100644
--- a/src/plugins/ui_actions/public/triggers/row_click_trigger.ts
+++ b/src/plugins/ui_actions/public/triggers/row_click_trigger.ts
@@ -18,7 +18,6 @@
*/
import { i18n } from '@kbn/i18n';
-import { IEmbeddable } from '../../../embeddable/public';
import { Trigger } from '.';
import { Datatable } from '../../../expressions';
@@ -35,7 +34,9 @@ export const rowClickTrigger: Trigger<'ROW_CLICK_TRIGGER'> = {
};
export interface RowClickContext {
- embeddable?: IEmbeddable;
+ // Need to make this unknown to prevent circular dependencies.
+ // Apps using this property will need to cast to `IEmbeddable`.
+ embeddable?: unknown;
data: {
/**
* Row index, starting from 0, where user clicked.
diff --git a/src/plugins/ui_actions/public/triggers/trigger.ts b/src/plugins/ui_actions/public/triggers/trigger.ts
index 2c019b09881d1..1b1231c132dde 100644
--- a/src/plugins/ui_actions/public/triggers/trigger.ts
+++ b/src/plugins/ui_actions/public/triggers/trigger.ts
@@ -32,8 +32,7 @@ import { TriggerContextMapping, TriggerId } from '../types';
*/
export interface Trigger {
/**
- * Unique name of the trigger as identified in `ui_actions` plugin trigger
- * registry, such as "SELECT_RANGE_TRIGGER" or "VALUE_CLICK_TRIGGER".
+ * Unique name of the trigger as identified in `ui_actions` plugin trigger registry.
*/
id: ID;
diff --git a/src/plugins/ui_actions/public/triggers/trigger_contract.ts b/src/plugins/ui_actions/public/triggers/trigger_contract.ts
index 04a75cb3a53d0..7e7fba0ba80d3 100644
--- a/src/plugins/ui_actions/public/triggers/trigger_contract.ts
+++ b/src/plugins/ui_actions/public/triggers/trigger_contract.ts
@@ -25,8 +25,7 @@ import { TriggerId, TriggerContextMapping } from '../types';
*/
export class TriggerContract {
/**
- * Unique name of the trigger as identified in `ui_actions` plugin trigger
- * registry, such as "SELECT_RANGE_TRIGGER" or "VALUE_CLICK_TRIGGER".
+ * Unique name of the trigger as identified in `ui_actions` plugin trigger registry.
*/
public readonly id: T;
diff --git a/src/plugins/ui_actions/public/types.ts b/src/plugins/ui_actions/public/types.ts
index 0266a755be926..62fac245514cd 100644
--- a/src/plugins/ui_actions/public/types.ts
+++ b/src/plugins/ui_actions/public/types.ts
@@ -20,17 +20,12 @@
import { ActionInternal } from './actions/action_internal';
import { TriggerInternal } from './triggers/trigger_internal';
import {
- SELECT_RANGE_TRIGGER,
- VALUE_CLICK_TRIGGER,
ROW_CLICK_TRIGGER,
- APPLY_FILTER_TRIGGER,
VISUALIZE_FIELD_TRIGGER,
VISUALIZE_GEO_FIELD_TRIGGER,
DEFAULT_TRIGGER,
RowClickContext,
} from './triggers';
-import type { RangeSelectContext, ValueClickContext } from '../../embeddable/public';
-import type { ApplyGlobalFilterActionContext } from '../../data/public';
export type TriggerRegistry = Map>;
export type ActionRegistry = Map;
@@ -49,10 +44,7 @@ export type TriggerContext = BaseContext;
export interface TriggerContextMapping {
[DEFAULT_TRIGGER]: TriggerContext;
- [SELECT_RANGE_TRIGGER]: RangeSelectContext;
- [VALUE_CLICK_TRIGGER]: ValueClickContext;
[ROW_CLICK_TRIGGER]: RowClickContext;
- [APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext;
[VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext;
[VISUALIZE_GEO_FIELD_TRIGGER]: VisualizeFieldContext;
}
diff --git a/src/plugins/vis_default_editor/public/components/agg_add.tsx b/src/plugins/vis_default_editor/public/components/agg_add.tsx
index e78f2fcc4453c..2da7b33139a8e 100644
--- a/src/plugins/vis_default_editor/public/components/agg_add.tsx
+++ b/src/plugins/vis_default_editor/public/components/agg_add.tsx
@@ -76,10 +76,17 @@ function DefaultEditorAggAdd({
);
- const isSchemaDisabled = (schema: Schema): boolean => {
+ const isMaxedCount = (schema: Schema): boolean => {
const count = group.filter((agg) => agg.schema === schema.name).length;
return count >= schema.max;
};
+ const isSchemaDisabled = (schema: Schema, maxedCount: boolean): boolean => {
+ return schema.disabled ?? maxedCount;
+ };
+ const maxTooltipText = i18n.translate('visDefaultEditor.aggAdd.maxBuckets', {
+ defaultMessage: 'Max {groupNameLabel} count reached',
+ values: { groupNameLabel },
+ });
return (
@@ -109,16 +116,21 @@ function DefaultEditorAggAdd({
)}
(
- onSelectSchema(schema)}
- >
- {schema.title}
-
- ))}
+ items={schemas.map((schema) => {
+ const maxedCount = isMaxedCount(schema);
+
+ return (
+ onSelectSchema(schema)}
+ toolTipContent={schema.tooltip ?? (maxedCount ? maxTooltipText : undefined)}
+ >
+ {schema.title}
+
+ );
+ })}
/>
diff --git a/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts b/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts
index 337533df50fad..90e2d792d3597 100644
--- a/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts
+++ b/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts
@@ -20,9 +20,10 @@
import { useCallback, useState } from 'react';
import { i18n } from '@kbn/i18n';
-import { Vis } from 'src/plugins/visualizations/public';
-import { DefaultEditorDataTab, DefaultEditorDataTabProps } from './data_tab';
+import { Vis } from '../../../../visualizations/public';
+
import { VisOptionsProps } from '../../vis_options_props';
+import { DefaultEditorDataTab, DefaultEditorDataTabProps } from './data_tab';
export interface OptionTab {
editor: React.ComponentType;
diff --git a/src/plugins/vis_default_editor/public/default_editor_controller.tsx b/src/plugins/vis_default_editor/public/default_editor_controller.tsx
index 707b14c23ea75..f44ea3e203b05 100644
--- a/src/plugins/vis_default_editor/public/default_editor_controller.tsx
+++ b/src/plugins/vis_default_editor/public/default_editor_controller.tsx
@@ -25,6 +25,7 @@ import { EuiErrorBoundary, EuiLoadingChart } from '@elastic/eui';
import { EditorRenderProps, IEditorController } from 'src/plugins/visualize/public';
import { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public';
+// @ts-ignore
const DefaultEditor = lazy(() => import('./default_editor'));
class DefaultEditorController implements IEditorController {
diff --git a/src/plugins/vis_default_editor/public/schemas.ts b/src/plugins/vis_default_editor/public/schemas.ts
index d95a6252331bf..7ecb4e54726b8 100644
--- a/src/plugins/vis_default_editor/public/schemas.ts
+++ b/src/plugins/vis_default_editor/public/schemas.ts
@@ -17,6 +17,7 @@
* under the License.
*/
+import { ReactNode } from 'react';
import _, { defaults } from 'lodash';
import { Optional } from '@kbn/utility-types';
@@ -42,6 +43,8 @@ export interface Schema {
hideCustomLabel?: boolean;
mustBeFirst?: boolean;
aggSettings?: any;
+ disabled?: boolean;
+ tooltip?: ReactNode;
}
export class Schemas implements ISchemas {
diff --git a/src/plugins/vis_type_markdown/public/to_ast.test.ts b/src/plugins/vis_type_markdown/public/to_ast.test.ts
index 1ad1fa0ee2517..4c7b570aef05d 100644
--- a/src/plugins/vis_type_markdown/public/to_ast.test.ts
+++ b/src/plugins/vis_type_markdown/public/to_ast.test.ts
@@ -42,12 +42,14 @@ describe('markdown vis toExpressionAst function', () => {
it('without params', () => {
vis.params = {};
+ // @ts-expect-error
const actual = toExpressionAst(vis);
expect(actual).toMatchSnapshot();
});
it('with params', () => {
vis.params = { markdown: '### my markdown', fontSize: 15, openLinksInNewTab: true };
+ // @ts-expect-error
const actual = toExpressionAst(vis);
expect(actual).toMatchSnapshot();
});
diff --git a/src/plugins/vis_type_markdown/public/to_ast.ts b/src/plugins/vis_type_markdown/public/to_ast.ts
index 9b481218b42ea..dc61acf722ad4 100644
--- a/src/plugins/vis_type_markdown/public/to_ast.ts
+++ b/src/plugins/vis_type_markdown/public/to_ast.ts
@@ -17,11 +17,11 @@
* under the License.
*/
-import { Vis } from '../../visualizations/public';
+import { VisToExpressionAst } from '../../visualizations/public';
import { buildExpression, buildExpressionFunction } from '../../expressions/public';
import { MarkdownVisExpressionFunctionDefinition } from './markdown_fn';
-export const toExpressionAst = (vis: Vis) => {
+export const toExpressionAst: VisToExpressionAst = (vis) => {
const { markdown, fontSize, openLinksInNewTab } = vis.params;
const markdownVis = buildExpressionFunction(
diff --git a/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx b/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx
index d0a7412238871..d87a0da740d75 100644
--- a/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx
+++ b/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx
@@ -31,7 +31,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
import {
- ColorModes,
+ ColorMode,
ColorRanges,
ColorSchemaOptions,
SwitchOption,
@@ -86,7 +86,7 @@ function MetricVisOptions({
);
const setColorMode: EuiButtonGroupProps['onChange'] = useCallback(
- (id: string) => setMetricValue('metricColorMode', id as ColorModes),
+ (id: string) => setMetricValue('metricColorMode', id as ColorMode),
[setMetricValue]
);
@@ -158,7 +158,7 @@ function MetricVisOptions({
colorSchemas={vis.type.editorConfig.collections.colorSchemas}
disabled={
stateParams.metric.colorsRange.length === 1 ||
- stateParams.metric.metricColorMode === ColorModes.NONE
+ stateParams.metric.metricColorMode === ColorMode.None
}
invertColors={stateParams.metric.invertColors}
setValue={setMetricValue as SetColorSchemaOptionsValue}
diff --git a/src/plugins/vis_type_metric/public/metric_vis_fn.ts b/src/plugins/vis_type_metric/public/metric_vis_fn.ts
index 20de22f50e63a..783ca3d3906ea 100644
--- a/src/plugins/vis_type_metric/public/metric_vis_fn.ts
+++ b/src/plugins/vis_type_metric/public/metric_vis_fn.ts
@@ -27,14 +27,14 @@ import {
Style,
} from '../../expressions/public';
import { visType, DimensionsVisParam, VisParams } from './types';
-import { ColorSchemas, vislibColorMaps, ColorModes } from '../../charts/public';
+import { ColorSchemas, vislibColorMaps, ColorMode } from '../../charts/public';
export type Input = Datatable;
interface Arguments {
percentageMode: boolean;
colorSchema: ColorSchemas;
- colorMode: ColorModes;
+ colorMode: ColorMode;
useRanges: boolean;
invertColors: boolean;
showLabels: boolean;
@@ -86,7 +86,7 @@ export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({
colorMode: {
types: ['string'],
default: '"None"',
- options: [ColorModes.NONE, ColorModes.LABELS, ColorModes.BACKGROUND],
+ options: [ColorMode.None, ColorMode.Labels, ColorMode.Background],
help: i18n.translate('visTypeMetric.function.colorMode.help', {
defaultMessage: 'Which part of metric to color',
}),
@@ -160,7 +160,7 @@ export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({
}),
},
},
- fn(input, args) {
+ fn(input, args, handlers) {
const dimensions: DimensionsVisParam = {
metrics: args.metric,
};
@@ -175,6 +175,9 @@ export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({
const fontSize = Number.parseInt(args.font.spec.fontSize || '', 10);
+ if (handlers?.inspectorAdapters?.tables) {
+ handlers.inspectorAdapters.tables.logDatatable('default', input);
+ }
return {
type: 'render',
as: 'metric_vis',
@@ -194,8 +197,8 @@ export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({
invertColors: args.invertColors,
style: {
bgFill: args.bgFill,
- bgColor: args.colorMode === ColorModes.BACKGROUND,
- labelColor: args.colorMode === ColorModes.LABELS,
+ bgColor: args.colorMode === ColorMode.Background,
+ labelColor: args.colorMode === ColorMode.Labels,
subText: args.subText,
fontSize,
},
diff --git a/src/plugins/vis_type_metric/public/metric_vis_type.ts b/src/plugins/vis_type_metric/public/metric_vis_type.ts
index f7c74e324053e..ba8f27b9412a2 100644
--- a/src/plugins/vis_type_metric/public/metric_vis_type.ts
+++ b/src/plugins/vis_type_metric/public/metric_vis_type.ts
@@ -20,7 +20,7 @@
import { i18n } from '@kbn/i18n';
import { BaseVisTypeOptions } from 'src/plugins/visualizations/public';
import { MetricVisOptions } from './components/metric_vis_options';
-import { ColorSchemas, colorSchemas, ColorModes } from '../../charts/public';
+import { ColorSchemas, colorSchemas, ColorMode } from '../../charts/public';
import { AggGroupNames } from '../../data/public';
import { Schemas } from '../../vis_default_editor/public';
import { toExpressionAst } from './to_ast';
@@ -42,7 +42,7 @@ export const createMetricVisTypeDefinition = (): BaseVisTypeOptions => ({
percentageMode: false,
useRanges: false,
colorSchema: ColorSchemas.GreenToRed,
- metricColorMode: ColorModes.NONE,
+ metricColorMode: ColorMode.None,
colorsRange: [{ from: 0, to: 10000 }],
labels: {
show: true,
@@ -62,19 +62,19 @@ export const createMetricVisTypeDefinition = (): BaseVisTypeOptions => ({
collections: {
metricColorMode: [
{
- id: ColorModes.NONE,
+ id: ColorMode.None,
label: i18n.translate('visTypeMetric.colorModes.noneOptionLabel', {
defaultMessage: 'None',
}),
},
{
- id: ColorModes.LABELS,
+ id: ColorMode.Labels,
label: i18n.translate('visTypeMetric.colorModes.labelsOptionLabel', {
defaultMessage: 'Labels',
}),
},
{
- id: ColorModes.BACKGROUND,
+ id: ColorMode.Background,
label: i18n.translate('visTypeMetric.colorModes.backgroundOptionLabel', {
defaultMessage: 'Background',
}),
diff --git a/src/plugins/vis_type_metric/public/types.ts b/src/plugins/vis_type_metric/public/types.ts
index e1f2c7721a426..e0ebfb36fa37d 100644
--- a/src/plugins/vis_type_metric/public/types.ts
+++ b/src/plugins/vis_type_metric/public/types.ts
@@ -19,7 +19,7 @@
import { Range } from '../../expressions/public';
import { SchemaConfig } from '../../visualizations/public';
-import { ColorModes, Labels, Style, ColorSchemas } from '../../charts/public';
+import { ColorMode, Labels, Style, ColorSchemas } from '../../charts/public';
export const visType = 'metric';
@@ -32,7 +32,7 @@ export interface MetricVisParam {
percentageMode: boolean;
useRanges: boolean;
colorSchema: ColorSchemas;
- metricColorMode: ColorModes;
+ metricColorMode: ColorMode;
colorsRange: Range[];
labels: Labels;
invertColors: boolean;
diff --git a/src/plugins/vis_type_table/public/components/table_visualization.tsx b/src/plugins/vis_type_table/public/components/table_visualization.tsx
index 2d38acc57519f..a1e4fad719dc4 100644
--- a/src/plugins/vis_type_table/public/components/table_visualization.tsx
+++ b/src/plugins/vis_type_table/public/components/table_visualization.tsx
@@ -23,6 +23,7 @@ import classNames from 'classnames';
import { CoreStart } from 'kibana/public';
import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
+import type { PersistedState } from 'src/plugins/visualizations/public';
import { KibanaContextProvider } from '../../../kibana_react/public';
import { TableVisConfig } from '../types';
import { TableContext } from '../table_vis_response_handler';
@@ -47,7 +48,7 @@ const TableVisualizationComponent = ({
handlers.done();
}, [handlers]);
- const uiStateProps = useUiState(handlers.uiState);
+ const uiStateProps = useUiState(handlers.uiState as PersistedState);
const className = classNames('tbvChart', {
// eslint-disable-next-line @typescript-eslint/naming-convention
diff --git a/src/plugins/vis_type_table/public/table_vis_fn.ts b/src/plugins/vis_type_table/public/table_vis_fn.ts
index 28990f28caf31..530f50ffd89b6 100644
--- a/src/plugins/vis_type_table/public/table_vis_fn.ts
+++ b/src/plugins/vis_type_table/public/table_vis_fn.ts
@@ -55,10 +55,13 @@ export const createTableVisFn = (): TableExpressionFunctionDefinition => ({
help: '',
},
},
- fn(input, args) {
+ fn(input, args, handlers) {
const visConfig = args.visConfig && JSON.parse(args.visConfig);
const convertedData = tableVisResponseHandler(input, visConfig.dimensions);
+ if (handlers?.inspectorAdapters?.tables) {
+ handlers.inspectorAdapters.tables.logDatatable('default', input);
+ }
return {
type: 'render',
as: 'table_vis',
diff --git a/src/plugins/vis_type_table/public/utils/use/use_ui_state.ts b/src/plugins/vis_type_table/public/utils/use/use_ui_state.ts
index 68bad16972ec2..cc43fc6bcb582 100644
--- a/src/plugins/vis_type_table/public/utils/use/use_ui_state.ts
+++ b/src/plugins/vis_type_table/public/utils/use/use_ui_state.ts
@@ -19,7 +19,7 @@
import { debounce, isEqual } from 'lodash';
import { useCallback, useEffect, useRef, useState } from 'react';
-import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
+import type { PersistedState } from 'src/plugins/visualizations/public';
import { ColumnWidthData, TableVisUiState, TableVisUseUiStateProps } from '../../types';
@@ -28,9 +28,7 @@ const defaultSort = {
direction: null,
};
-export const useUiState = (
- uiState: IInterpreterRenderHandlers['uiState']
-): TableVisUseUiStateProps => {
+export const useUiState = (uiState: PersistedState): TableVisUseUiStateProps => {
const [sort, setSortState] = useState(
uiState?.get('vis.params.sort') || defaultSort
);
diff --git a/src/plugins/vis_type_tagcloud/public/tag_cloud_fn.ts b/src/plugins/vis_type_tagcloud/public/tag_cloud_fn.ts
index ff59572e0817d..3ed203dd22ef4 100644
--- a/src/plugins/vis_type_tagcloud/public/tag_cloud_fn.ts
+++ b/src/plugins/vis_type_tagcloud/public/tag_cloud_fn.ts
@@ -95,7 +95,7 @@ export const createTagCloudFn = (): TagcloudExpressionFunctionDefinition => ({
}),
},
},
- fn(input, args) {
+ fn(input, args, handlers) {
const visParams = {
scale: args.scale,
orientation: args.orientation,
@@ -109,6 +109,9 @@ export const createTagCloudFn = (): TagcloudExpressionFunctionDefinition => ({
visParams.bucket = args.bucket;
}
+ if (handlers?.inspectorAdapters?.tables) {
+ handlers.inspectorAdapters.tables.logDatatable('default', input);
+ }
return {
type: 'render',
as: 'tagloud_vis',
diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/decorators/__snapshots__/area_decorator.test.js.snap b/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/decorators/__snapshots__/area_decorator.test.js.snap
index 7ded8e2254aa9..fceb9c3fdb819 100644
--- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/decorators/__snapshots__/area_decorator.test.js.snap
+++ b/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/decorators/__snapshots__/area_decorator.test.js.snap
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`src/legacy/core_plugins/metrics/public/visualizations/views/timeseries/decorators/area_decorator.js should render and match a snapshot 1`] = `
- should render and match a snapshot 1`] = `
-
,
domNode
diff --git a/src/plugins/vis_type_timeseries/server/routes/fields.ts b/src/plugins/vis_type_timeseries/server/routes/fields.ts
index a9a890845d154..e787fd8d08a29 100644
--- a/src/plugins/vis_type_timeseries/server/routes/fields.ts
+++ b/src/plugins/vis_type_timeseries/server/routes/fields.ts
@@ -39,7 +39,7 @@ export const fieldsRoutes = (framework: Framework) => {
return res.customError({
body: err.output.payload,
statusCode: err.output.statusCode,
- headers: err.output.headers,
+ headers: err.output.headers as { [key: string]: string },
});
}
diff --git a/src/plugins/vis_type_vislib/kibana.json b/src/plugins/vis_type_vislib/kibana.json
index 720abff16b7c7..175c21f47c182 100644
--- a/src/plugins/vis_type_vislib/kibana.json
+++ b/src/plugins/vis_type_vislib/kibana.json
@@ -4,6 +4,5 @@
"server": true,
"ui": true,
"requiredPlugins": ["charts", "data", "expressions", "visualizations", "kibanaLegacy"],
- "optionalPlugins": ["visTypeXy"],
- "requiredBundles": ["kibanaUtils", "visDefaultEditor"]
+ "requiredBundles": ["kibanaUtils", "visDefaultEditor", "visTypeXy"]
}
diff --git a/src/plugins/vis_type_vislib/public/area.ts b/src/plugins/vis_type_vislib/public/area.ts
index ec7bce254f586..389daca6d1776 100644
--- a/src/plugins/vis_type_vislib/public/area.ts
+++ b/src/plugins/vis_type_vislib/public/area.ts
@@ -17,172 +17,14 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
-// @ts-ignore
-import { palettes } from '@elastic/eui/lib/services';
-// @ts-ignore
-import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
+import { xyVisTypes } from '../../vis_type_xy/public';
+import { BaseVisTypeOptions } from '../../visualizations/public';
-import { AggGroupNames } from '../../data/public';
-import { Schemas } from '../../vis_default_editor/public';
-import {
- Positions,
- ChartTypes,
- ChartModes,
- InterpolationModes,
- AxisTypes,
- ScaleTypes,
- AxisModes,
- ThresholdLineStyles,
- getConfigCollections,
-} from './utils/collections';
-import { getAreaOptionTabs, countLabel } from './utils/common_config';
-import { Rotates } from '../../charts/public';
-import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public';
import { toExpressionAst } from './to_ast';
import { BasicVislibParams } from './types';
export const areaVisTypeDefinition: BaseVisTypeOptions = {
- name: 'area',
- title: i18n.translate('visTypeVislib.area.areaTitle', { defaultMessage: 'Area' }),
- icon: 'visArea',
- description: i18n.translate('visTypeVislib.area.areaDescription', {
- defaultMessage: 'Emphasize the data between an axis and a line.',
- }),
- getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush],
+ ...(xyVisTypes.area() as BaseVisTypeOptions),
toExpressionAst,
- visConfig: {
- defaults: {
- type: 'area',
- grid: {
- categoryLines: false,
- },
- categoryAxes: [
- {
- id: 'CategoryAxis-1',
- type: AxisTypes.CATEGORY,
- position: Positions.BOTTOM,
- show: true,
- style: {},
- scale: {
- type: ScaleTypes.LINEAR,
- },
- labels: {
- show: true,
- filter: true,
- truncate: 100,
- },
- title: {},
- },
- ],
- valueAxes: [
- {
- id: 'ValueAxis-1',
- name: 'LeftAxis-1',
- type: AxisTypes.VALUE,
- position: Positions.LEFT,
- show: true,
- style: {},
- scale: {
- type: ScaleTypes.LINEAR,
- mode: AxisModes.NORMAL,
- },
- labels: {
- show: true,
- rotate: Rotates.HORIZONTAL,
- filter: false,
- truncate: 100,
- },
- title: {
- text: countLabel,
- },
- },
- ],
- seriesParams: [
- {
- show: true,
- type: ChartTypes.AREA,
- mode: ChartModes.STACKED,
- data: {
- label: countLabel,
- id: '1',
- },
- drawLinesBetweenPoints: true,
- lineWidth: 2,
- showCircles: true,
- interpolate: InterpolationModes.LINEAR,
- valueAxis: 'ValueAxis-1',
- },
- ],
- addTooltip: true,
- addLegend: true,
- legendPosition: Positions.RIGHT,
- times: [],
- addTimeMarker: false,
- thresholdLine: {
- show: false,
- value: 10,
- width: 1,
- style: ThresholdLineStyles.FULL,
- color: euiPaletteColorBlind()[9],
- },
- labels: {},
- },
- },
- editorConfig: {
- collections: getConfigCollections(),
- optionTabs: getAreaOptionTabs(),
- schemas: new Schemas([
- {
- group: AggGroupNames.Metrics,
- name: 'metric',
- title: i18n.translate('visTypeVislib.area.metricsTitle', {
- defaultMessage: 'Y-axis',
- }),
- aggFilter: ['!geo_centroid', '!geo_bounds'],
- min: 1,
- defaults: [{ schema: 'metric', type: 'count' }],
- },
- {
- group: AggGroupNames.Metrics,
- name: 'radius',
- title: i18n.translate('visTypeVislib.area.radiusTitle', {
- defaultMessage: 'Dot size',
- }),
- min: 0,
- max: 1,
- aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'segment',
- title: i18n.translate('visTypeVislib.area.segmentTitle', {
- defaultMessage: 'X-axis',
- }),
- min: 0,
- max: 1,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'group',
- title: i18n.translate('visTypeVislib.area.groupTitle', {
- defaultMessage: 'Split series',
- }),
- min: 0,
- max: 3,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'split',
- title: i18n.translate('visTypeVislib.area.splitTitle', {
- defaultMessage: 'Split chart',
- }),
- min: 0,
- max: 1,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- ]),
- },
+ visualization: undefined,
};
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx b/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx
deleted file mode 100644
index 63881fea1ad88..0000000000000
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx
+++ /dev/null
@@ -1,248 +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 React from 'react';
-import { mount, shallow } from 'enzyme';
-
-import { IAggConfig, IAggType } from 'src/plugins/data/public';
-import MetricsAxisOptions from './index';
-import { BasicVislibParams, SeriesParam, ValueAxis } from '../../../types';
-import { ValidationVisOptionsProps } from '../../common';
-import { Positions } from '../../../utils/collections';
-import { ValueAxesPanel } from './value_axes_panel';
-import { CategoryAxisPanel } from './category_axis_panel';
-import { ChartTypes } from '../../../utils/collections';
-import { defaultValueAxisId, valueAxis, seriesParam, categoryAxis } from './mocks';
-
-jest.mock('./series_panel', () => ({
- SeriesPanel: () => 'SeriesPanel',
-}));
-jest.mock('./category_axis_panel', () => ({
- CategoryAxisPanel: () => 'CategoryAxisPanel',
-}));
-jest.mock('./value_axes_panel', () => ({
- ValueAxesPanel: () => 'ValueAxesPanel',
-}));
-
-const SERIES_PARAMS = 'seriesParams';
-const VALUE_AXES = 'valueAxes';
-
-const aggCount: IAggConfig = {
- id: '1',
- type: { name: 'count' },
- makeLabel: () => 'Count',
-} as IAggConfig;
-
-const aggAverage: IAggConfig = {
- id: '2',
- type: { name: 'average' } as IAggType,
- makeLabel: () => 'Average',
-} as IAggConfig;
-
-const createAggs = (aggs: any[]) => ({
- aggs,
- bySchemaName: () => aggs,
-});
-
-describe('MetricsAxisOptions component', () => {
- let setValue: jest.Mock;
- let defaultProps: ValidationVisOptionsProps;
- let axis: ValueAxis;
- let axisRight: ValueAxis;
- let chart: SeriesParam;
-
- beforeEach(() => {
- setValue = jest.fn();
-
- axis = {
- ...valueAxis,
- name: 'LeftAxis-1',
- position: Positions.LEFT,
- };
- axisRight = {
- ...valueAxis,
- id: 'ValueAxis-2',
- name: 'RightAxis-1',
- position: Positions.RIGHT,
- };
- chart = {
- ...seriesParam,
- type: ChartTypes.AREA,
- };
-
- defaultProps = {
- aggs: createAggs([aggCount]),
- isTabSelected: true,
- vis: {
- type: {
- type: ChartTypes.AREA,
- schemas: { metrics: [{ name: 'metric' }] },
- },
- setState: jest.fn(),
- serialize: jest.fn(),
- },
- stateParams: {
- valueAxes: [axis],
- seriesParams: [chart],
- categoryAxes: [categoryAxis],
- grid: { valueAxis: defaultValueAxisId },
- },
- setValue,
- } as any;
- });
-
- it('should init with the default set of props', () => {
- const comp = shallow();
-
- expect(comp).toMatchSnapshot();
- });
-
- describe('useEffect', () => {
- it('should update series when new agg is added', () => {
- const comp = mount();
- comp.setProps({
- aggs: createAggs([aggCount, aggAverage]),
- });
-
- const updatedSeries = [chart, { ...chart, data: { id: '2', label: aggAverage.makeLabel() } }];
- expect(setValue).toHaveBeenLastCalledWith(SERIES_PARAMS, updatedSeries);
- });
-
- it('should update series when new agg label is changed', () => {
- const comp = mount();
- const agg = { id: aggCount.id, makeLabel: () => 'New label' };
- comp.setProps({
- aggs: createAggs([agg]),
- });
-
- const updatedSeries = [{ ...chart, data: { id: agg.id, label: agg.makeLabel() } }];
- expect(setValue).toHaveBeenCalledWith(SERIES_PARAMS, updatedSeries);
- });
- });
-
- describe('updateAxisTitle', () => {
- it('should not update the value axis title if custom title was set', () => {
- defaultProps.stateParams.valueAxes[0].title.text = 'Custom title';
- const comp = mount();
- const newAgg = {
- ...aggCount,
- makeLabel: () => 'Custom label',
- };
- comp.setProps({
- aggs: createAggs([newAgg]),
- });
- const updatedValues = [{ ...axis, title: { text: newAgg.makeLabel() } }];
- expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES, updatedValues);
- });
-
- it('should set the custom title to match the value axis label when only one agg exists for that axis', () => {
- const comp = mount();
- const agg = {
- id: aggCount.id,
- params: { customLabel: 'Custom label' },
- makeLabel: () => 'Custom label',
- };
- comp.setProps({
- aggs: createAggs([agg]),
- });
-
- const updatedSeriesParams = [{ ...chart, data: { ...chart.data, label: agg.makeLabel() } }];
- const updatedValues = [{ ...axis, title: { text: agg.makeLabel() } }];
-
- expect(setValue).toHaveBeenCalledTimes(5);
- expect(setValue).toHaveBeenNthCalledWith(3, SERIES_PARAMS, updatedSeriesParams);
- expect(setValue).toHaveBeenNthCalledWith(5, SERIES_PARAMS, updatedSeriesParams);
- expect(setValue).toHaveBeenNthCalledWith(4, VALUE_AXES, updatedValues);
- });
-
- it('should not set the custom title to match the value axis label when more than one agg exists for that axis', () => {
- const comp = mount();
- const agg = { id: aggCount.id, makeLabel: () => 'Custom label' };
- comp.setProps({
- aggs: createAggs([agg, aggAverage]),
- stateParams: {
- ...defaultProps.stateParams,
- seriesParams: [chart, chart],
- },
- });
-
- expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES);
- });
-
- it('should not overwrite the custom title with the value axis label if the custom title has been changed', () => {
- defaultProps.stateParams.valueAxes[0].title.text = 'Custom title';
- const comp = mount();
- const agg = {
- id: aggCount.id,
- params: { customLabel: 'Custom label' },
- makeLabel: () => 'Custom label',
- };
- comp.setProps({
- aggs: createAggs([agg]),
- });
-
- expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES);
- });
- });
-
- it('should add value axis', () => {
- const comp = shallow();
- comp.find(ValueAxesPanel).prop('addValueAxis')();
-
- expect(setValue).toHaveBeenCalledWith(VALUE_AXES, [axis, axisRight]);
- });
-
- describe('removeValueAxis', () => {
- beforeEach(() => {
- defaultProps.stateParams.valueAxes = [axis, axisRight];
- });
-
- it('should remove value axis', () => {
- const comp = shallow();
- comp.find(ValueAxesPanel).prop('removeValueAxis')(axis);
-
- expect(setValue).toHaveBeenCalledWith(VALUE_AXES, [axisRight]);
- });
-
- it('should update seriesParams "valueAxis" prop', () => {
- const updatedSeriesParam = { ...chart, valueAxis: 'ValueAxis-2' };
- const comp = shallow();
- comp.find(ValueAxesPanel).prop('removeValueAxis')(axis);
-
- expect(setValue).toHaveBeenCalledWith(SERIES_PARAMS, [updatedSeriesParam]);
- });
-
- it('should reset grid "valueAxis" prop', () => {
- const updatedGrid = { valueAxis: undefined };
- defaultProps.stateParams.seriesParams[0].valueAxis = 'ValueAxis-2';
- const comp = shallow();
- comp.find(ValueAxesPanel).prop('removeValueAxis')(axis);
-
- expect(setValue).toHaveBeenCalledWith('grid', updatedGrid);
- });
- });
-
- it('should update axis value when when category position chnaged', () => {
- const comp = shallow();
- comp.find(CategoryAxisPanel).prop('onPositionChanged')(Positions.LEFT);
-
- const updatedValues = [{ ...axis, name: 'BottomAxis-1', position: Positions.BOTTOM }];
- expect(setValue).toHaveBeenCalledWith(VALUE_AXES, updatedValues);
- });
-});
diff --git a/src/plugins/vis_type_vislib/public/editor/collections.ts b/src/plugins/vis_type_vislib/public/editor/collections.ts
new file mode 100644
index 0000000000000..f1caa0754b0b3
--- /dev/null
+++ b/src/plugins/vis_type_vislib/public/editor/collections.ts
@@ -0,0 +1,73 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+
+import { colorSchemas } from '../../../charts/public';
+import { getPositions, getScaleTypes } from '../../../vis_type_xy/public';
+
+import { Alignment, GaugeType } from '../types';
+
+export const getGaugeTypes = () => [
+ {
+ text: i18n.translate('visTypeVislib.gauge.gaugeTypes.arcText', {
+ defaultMessage: 'Arc',
+ }),
+ value: GaugeType.Arc,
+ },
+ {
+ text: i18n.translate('visTypeVislib.gauge.gaugeTypes.circleText', {
+ defaultMessage: 'Circle',
+ }),
+ value: GaugeType.Circle,
+ },
+];
+
+export const getAlignments = () => [
+ {
+ text: i18n.translate('visTypeVislib.gauge.alignmentAutomaticTitle', {
+ defaultMessage: 'Automatic',
+ }),
+ value: Alignment.Automatic,
+ },
+ {
+ text: i18n.translate('visTypeVislib.gauge.alignmentHorizontalTitle', {
+ defaultMessage: 'Horizontal',
+ }),
+ value: Alignment.Horizontal,
+ },
+ {
+ text: i18n.translate('visTypeVislib.gauge.alignmentVerticalTitle', {
+ defaultMessage: 'Vertical',
+ }),
+ value: Alignment.Vertical,
+ },
+];
+
+export const getGaugeCollections = () => ({
+ gaugeTypes: getGaugeTypes(),
+ alignments: getAlignments(),
+ colorSchemas,
+});
+
+export const getHeatmapCollections = () => ({
+ legendPositions: getPositions(),
+ scales: getScaleTypes(),
+ colorSchemas,
+});
diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/index.tsx
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/gauge/index.tsx
rename to src/plugins/vis_type_vislib/public/editor/components/gauge/index.tsx
diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/labels_panel.tsx
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx
rename to src/plugins/vis_type_vislib/public/editor/components/gauge/labels_panel.tsx
diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/ranges_panel.tsx
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx
rename to src/plugins/vis_type_vislib/public/editor/components/gauge/ranges_panel.tsx
diff --git a/src/plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/style_panel.tsx
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx
rename to src/plugins/vis_type_vislib/public/editor/components/gauge/style_panel.tsx
diff --git a/src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx
similarity index 97%
rename from src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx
rename to src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx
index 312cf60fda6b0..f5b853accb08e 100644
--- a/src/plugins/vis_type_vislib/public/components/options/heatmap/index.tsx
+++ b/src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx
@@ -23,7 +23,8 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
+import { VisOptionsProps } from '../../../../../vis_default_editor/public';
+import { ValueAxis } from '../../../../../vis_type_xy/public';
import {
BasicOptions,
ColorRanges,
@@ -34,8 +35,8 @@ import {
SetColorSchemaOptionsValue,
SetColorRangeValue,
} from '../../../../../charts/public';
+
import { HeatmapVisParams } from '../../../heatmap';
-import { ValueAxis } from '../../../types';
import { LabelsPanel } from './labels_panel';
function HeatmapOptions(props: VisOptionsProps) {
diff --git a/src/plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx
similarity index 96%
rename from src/plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx
rename to src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx
index 4998a8fd02521..8ec06ea50ec12 100644
--- a/src/plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx
+++ b/src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx
@@ -23,10 +23,11 @@ import { EuiColorPicker, EuiFormRow, EuiPanel, EuiSpacer, EuiTitle } from '@elas
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
-import { ValueAxis } from '../../../types';
-import { HeatmapVisParams } from '../../../heatmap';
+import { VisOptionsProps } from '../../../../../vis_default_editor/public';
import { SwitchOption } from '../../../../../charts/public';
+import { ValueAxis } from '../../../../../vis_type_xy/public';
+
+import { HeatmapVisParams } from '../../../heatmap';
const VERTICAL_ROTATION = 270;
diff --git a/src/plugins/vis_type_vislib/public/components/options/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/index.tsx
similarity index 71%
rename from src/plugins/vis_type_vislib/public/components/options/index.tsx
rename to src/plugins/vis_type_vislib/public/editor/components/index.tsx
index 18c41bf289b11..ed8c8239a07b6 100644
--- a/src/plugins/vis_type_vislib/public/components/options/index.tsx
+++ b/src/plugins/vis_type_vislib/public/editor/components/index.tsx
@@ -19,18 +19,15 @@
import React, { lazy } from 'react';
-import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
-import { ValidationVisOptionsProps } from '../common';
+import { VisOptionsProps } from '../../../../vis_default_editor/public';
+
import { GaugeVisParams } from '../../gauge';
import { PieVisParams } from '../../pie';
-import { BasicVislibParams } from '../../types';
import { HeatmapVisParams } from '../../heatmap';
const GaugeOptionsLazy = lazy(() => import('./gauge'));
const PieOptionsLazy = lazy(() => import('./pie'));
-const PointSeriesOptionsLazy = lazy(() => import('./point_series'));
const HeatmapOptionsLazy = lazy(() => import('./heatmap'));
-const MetricsAxisOptionsLazy = lazy(() => import('./metrics_axes'));
export const GaugeOptions = (props: VisOptionsProps) => (
@@ -38,14 +35,6 @@ export const GaugeOptions = (props: VisOptionsProps) => (
export const PieOptions = (props: VisOptionsProps) => ;
-export const PointSeriesOptions = (props: ValidationVisOptionsProps) => (
-
-);
-
export const HeatmapOptions = (props: VisOptionsProps) => (
);
-
-export const MetricsAxisOptions = (props: ValidationVisOptionsProps) => (
-
-);
diff --git a/src/plugins/vis_type_vislib/public/components/options/pie.tsx b/src/plugins/vis_type_vislib/public/editor/components/pie.tsx
similarity index 96%
rename from src/plugins/vis_type_vislib/public/components/options/pie.tsx
rename to src/plugins/vis_type_vislib/public/editor/components/pie.tsx
index 30828bfc6a3ea..1c3aa501b4d00 100644
--- a/src/plugins/vis_type_vislib/public/components/options/pie.tsx
+++ b/src/plugins/vis_type_vislib/public/editor/components/pie.tsx
@@ -22,9 +22,10 @@ import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
-import { TruncateLabelsOption } from '../common';
+import { VisOptionsProps } from '../../../../vis_default_editor/public';
import { BasicOptions, SwitchOption } from '../../../../charts/public';
+import { TruncateLabelsOption } from '../../../../vis_type_xy/public';
+
import { PieVisParams } from '../../pie';
function PieOptions(props: VisOptionsProps) {
diff --git a/src/plugins/vis_type_vislib/public/editor/index.ts b/src/plugins/vis_type_vislib/public/editor/index.ts
new file mode 100644
index 0000000000000..2a73b1ad8fa68
--- /dev/null
+++ b/src/plugins/vis_type_vislib/public/editor/index.ts
@@ -0,0 +1,21 @@
+/*
+ * 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 * from './collections';
+export * from './components';
diff --git a/src/plugins/vis_type_vislib/public/gauge.ts b/src/plugins/vis_type_vislib/public/gauge.ts
index 7cc8e03c9e4c2..de32ee17a21bf 100644
--- a/src/plugins/vis_type_vislib/public/gauge.ts
+++ b/src/plugins/vis_type_vislib/public/gauge.ts
@@ -19,24 +19,25 @@
import { i18n } from '@kbn/i18n';
+import { ColorMode, ColorSchemas, ColorSchemaParams, Labels, Style } from '../../charts/public';
import { RangeValues, Schemas } from '../../vis_default_editor/public';
import { AggGroupNames } from '../../data/public';
-import { GaugeOptions } from './components/options';
-import { getGaugeCollections, Alignments, GaugeTypes } from './utils/collections';
-import { ColorModes, ColorSchemas, ColorSchemaParams, Labels, Style } from '../../charts/public';
-import { toExpressionAst } from './to_ast';
import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../visualizations/public';
-import { BasicVislibParams } from './types';
+
+import { Alignment, GaugeType, BasicVislibParams, VislibChartType } from './types';
+import { getGaugeCollections } from './editor';
+import { toExpressionAst } from './to_ast';
+import { GaugeOptions } from './editor/components';
export interface Gauge extends ColorSchemaParams {
backStyle: 'Full';
gaugeStyle: 'Full';
orientation: 'vertical';
type: 'meter';
- alignment: Alignments;
+ alignment: Alignment;
colorsRange: RangeValues[];
extendRange: boolean;
- gaugeType: GaugeTypes;
+ gaugeType: GaugeType;
labels: Labels;
percentageMode: boolean;
outline?: boolean;
@@ -67,20 +68,20 @@ export const gaugeVisTypeDefinition: BaseVisTypeOptions = {
toExpressionAst,
visConfig: {
defaults: {
- type: 'gauge',
+ type: VislibChartType.Gauge,
addTooltip: true,
addLegend: true,
isDisplayWarning: false,
gauge: {
- alignment: Alignments.AUTOMATIC,
+ alignment: Alignment.Automatic,
extendRange: true,
percentageMode: false,
- gaugeType: GaugeTypes.ARC,
+ gaugeType: GaugeType.Arc,
gaugeStyle: 'Full',
backStyle: 'Full',
orientation: 'vertical',
colorSchema: ColorSchemas.GreenToRed,
- gaugeColorMode: ColorModes.LABELS,
+ gaugeColorMode: ColorMode.Labels,
colorsRange: [
{ from: 0, to: 50 },
{ from: 50, to: 75 },
diff --git a/src/plugins/vis_type_vislib/public/goal.ts b/src/plugins/vis_type_vislib/public/goal.ts
index 46878ca82e45a..56361421261fc 100644
--- a/src/plugins/vis_type_vislib/public/goal.ts
+++ b/src/plugins/vis_type_vislib/public/goal.ts
@@ -19,14 +19,14 @@
import { i18n } from '@kbn/i18n';
-import { GaugeOptions } from './components/options';
-import { getGaugeCollections, GaugeTypes } from './utils/collections';
-import { ColorModes, ColorSchemas } from '../../charts/public';
import { AggGroupNames } from '../../data/public';
import { Schemas } from '../../vis_default_editor/public';
-import { toExpressionAst } from './to_ast';
+import { ColorMode, ColorSchemas } from '../../charts/public';
import { BaseVisTypeOptions } from '../../visualizations/public';
-import { BasicVislibParams } from './types';
+
+import { getGaugeCollections, GaugeOptions } from './editor';
+import { toExpressionAst } from './to_ast';
+import { GaugeType, BasicVislibParams } from './types';
export const goalVisTypeDefinition: BaseVisTypeOptions = {
name: 'goal',
@@ -46,13 +46,13 @@ export const goalVisTypeDefinition: BaseVisTypeOptions = {
verticalSplit: false,
autoExtend: false,
percentageMode: true,
- gaugeType: GaugeTypes.ARC,
+ gaugeType: GaugeType.Arc,
gaugeStyle: 'Full',
backStyle: 'Full',
orientation: 'vertical',
useRanges: false,
colorSchema: ColorSchemas.GreenToRed,
- gaugeColorMode: ColorModes.NONE,
+ gaugeColorMode: ColorMode.None,
colorsRange: [{ from: 0, to: 10000 }],
invertColors: false,
labels: {
diff --git a/src/plugins/vis_type_vislib/public/heatmap.ts b/src/plugins/vis_type_vislib/public/heatmap.ts
index c408ac140dd46..4a815fd8b2c73 100644
--- a/src/plugins/vis_type_vislib/public/heatmap.ts
+++ b/src/plugins/vis_type_vislib/public/heatmap.ts
@@ -18,15 +18,17 @@
*/
import { i18n } from '@kbn/i18n';
+import { Position } from '@elastic/charts';
import { RangeValues, Schemas } from '../../vis_default_editor/public';
import { AggGroupNames } from '../../data/public';
-import { AxisTypes, getHeatmapCollections, Positions, ScaleTypes } from './utils/collections';
-import { HeatmapOptions } from './components/options';
-import { TimeMarker } from './vislib/visualizations/time_marker';
-import { BasicVislibParams, CommonVislibParams, ValueAxis } from './types';
import { ColorSchemas, ColorSchemaParams } from '../../charts/public';
-import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public';
+import { VIS_EVENT_TO_TRIGGER, BaseVisTypeOptions } from '../../visualizations/public';
+import { ValueAxis, ScaleType, AxisType } from '../../vis_type_xy/public';
+
+import { HeatmapOptions, getHeatmapCollections } from './editor';
+import { TimeMarker } from './vislib/visualizations/time_marker';
+import { CommonVislibParams, BasicVislibParams, VislibChartType } from './types';
import { toExpressionAst } from './to_ast';
export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaParams {
@@ -48,15 +50,15 @@ export const heatmapVisTypeDefinition: BaseVisTypeOptions = {
description: i18n.translate('visTypeVislib.heatmap.heatmapDescription', {
defaultMessage: 'Shade data in cells in a matrix.',
}),
- getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter],
toExpressionAst,
+ getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter],
visConfig: {
defaults: {
- type: 'heatmap',
+ type: VislibChartType.Heatmap,
addTooltip: true,
addLegend: true,
enableHover: false,
- legendPosition: Positions.RIGHT,
+ legendPosition: Position.Right,
times: [],
colorsNumber: 4,
colorSchema: ColorSchemas.Greens,
@@ -68,9 +70,9 @@ export const heatmapVisTypeDefinition: BaseVisTypeOptions = {
{
show: false,
id: 'ValueAxis-1',
- type: AxisTypes.VALUE,
+ type: AxisType.Value,
scale: {
- type: ScaleTypes.LINEAR,
+ type: ScaleType.Linear,
defaultYExtents: false,
},
labels: {
diff --git a/src/plugins/vis_type_vislib/public/histogram.ts b/src/plugins/vis_type_vislib/public/histogram.ts
index de4855ba9aa2b..7424ef5c4df27 100644
--- a/src/plugins/vis_type_vislib/public/histogram.ts
+++ b/src/plugins/vis_type_vislib/public/histogram.ts
@@ -17,174 +17,14 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
-// @ts-ignore
-import { palettes } from '@elastic/eui/lib/services';
-// @ts-ignore
-import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
+import { xyVisTypes } from '../../vis_type_xy/public';
+import { BaseVisTypeOptions } from '../../visualizations/public';
-import { AggGroupNames } from '../../data/public';
-import { Schemas } from '../../vis_default_editor/public';
-import {
- Positions,
- ChartTypes,
- ChartModes,
- AxisTypes,
- ScaleTypes,
- AxisModes,
- ThresholdLineStyles,
- getConfigCollections,
-} from './utils/collections';
-import { getAreaOptionTabs, countLabel } from './utils/common_config';
-import { Rotates } from '../../charts/public';
-import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public';
-import { BasicVislibParams } from './types';
import { toExpressionAst } from './to_ast';
+import { BasicVislibParams } from './types';
export const histogramVisTypeDefinition: BaseVisTypeOptions = {
- name: 'histogram',
- title: i18n.translate('visTypeVislib.histogram.histogramTitle', {
- defaultMessage: 'Vertical bar',
- }),
- icon: 'visBarVertical',
- description: i18n.translate('visTypeVislib.histogram.histogramDescription', {
- defaultMessage: 'Present data in vertical bars on an axis.',
- }),
- getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush],
+ ...(xyVisTypes.histogram() as BaseVisTypeOptions),
toExpressionAst,
- visConfig: {
- defaults: {
- type: 'histogram',
- grid: {
- categoryLines: false,
- },
- categoryAxes: [
- {
- id: 'CategoryAxis-1',
- type: AxisTypes.CATEGORY,
- position: Positions.BOTTOM,
- show: true,
- style: {},
- scale: {
- type: ScaleTypes.LINEAR,
- },
- labels: {
- show: true,
- filter: true,
- truncate: 100,
- },
- title: {},
- },
- ],
- valueAxes: [
- {
- id: 'ValueAxis-1',
- name: 'LeftAxis-1',
- type: AxisTypes.VALUE,
- position: Positions.LEFT,
- show: true,
- style: {},
- scale: {
- type: ScaleTypes.LINEAR,
- mode: AxisModes.NORMAL,
- },
- labels: {
- show: true,
- rotate: Rotates.HORIZONTAL,
- filter: false,
- truncate: 100,
- },
- title: {
- text: countLabel,
- },
- },
- ],
- seriesParams: [
- {
- show: true,
- type: ChartTypes.HISTOGRAM,
- mode: ChartModes.STACKED,
- data: {
- label: countLabel,
- id: '1',
- },
- valueAxis: 'ValueAxis-1',
- drawLinesBetweenPoints: true,
- lineWidth: 2,
- showCircles: true,
- },
- ],
- addTooltip: true,
- addLegend: true,
- legendPosition: Positions.RIGHT,
- times: [],
- addTimeMarker: false,
- labels: {
- show: false,
- },
- thresholdLine: {
- show: false,
- value: 10,
- width: 1,
- style: ThresholdLineStyles.FULL,
- color: euiPaletteColorBlind()[9],
- },
- },
- },
- editorConfig: {
- collections: getConfigCollections(),
- optionTabs: getAreaOptionTabs(),
- schemas: new Schemas([
- {
- group: AggGroupNames.Metrics,
- name: 'metric',
- title: i18n.translate('visTypeVislib.histogram.metricTitle', {
- defaultMessage: 'Y-axis',
- }),
- min: 1,
- aggFilter: ['!geo_centroid', '!geo_bounds'],
- defaults: [{ schema: 'metric', type: 'count' }],
- },
- {
- group: AggGroupNames.Metrics,
- name: 'radius',
- title: i18n.translate('visTypeVislib.histogram.radiusTitle', {
- defaultMessage: 'Dot size',
- }),
- min: 0,
- max: 1,
- aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'segment',
- title: i18n.translate('visTypeVislib.histogram.segmentTitle', {
- defaultMessage: 'X-axis',
- }),
- min: 0,
- max: 1,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'group',
- title: i18n.translate('visTypeVislib.histogram.groupTitle', {
- defaultMessage: 'Split series',
- }),
- min: 0,
- max: 3,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'split',
- title: i18n.translate('visTypeVislib.histogram.splitTitle', {
- defaultMessage: 'Split chart',
- }),
- min: 0,
- max: 1,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- ]),
- },
+ visualization: undefined,
};
diff --git a/src/plugins/vis_type_vislib/public/horizontal_bar.ts b/src/plugins/vis_type_vislib/public/horizontal_bar.ts
index 144e63224533b..9e919c66cb365 100644
--- a/src/plugins/vis_type_vislib/public/horizontal_bar.ts
+++ b/src/plugins/vis_type_vislib/public/horizontal_bar.ts
@@ -17,171 +17,14 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
-// @ts-ignore
-import { palettes, euiPaletteColorBlind } from '@elastic/eui/lib/services';
+import { xyVisTypes } from '../../vis_type_xy/public';
+import { BaseVisTypeOptions } from '../../visualizations/public';
-import { AggGroupNames } from '../../data/public';
-import { Schemas } from '../../vis_default_editor/public';
-import {
- Positions,
- ChartTypes,
- ChartModes,
- AxisTypes,
- ScaleTypes,
- AxisModes,
- ThresholdLineStyles,
- getConfigCollections,
-} from './utils/collections';
-import { getAreaOptionTabs, countLabel } from './utils/common_config';
-import { Rotates } from '../../charts/public';
-import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public';
-import { BasicVislibParams } from './types';
import { toExpressionAst } from './to_ast';
+import { BasicVislibParams } from './types';
export const horizontalBarVisTypeDefinition: BaseVisTypeOptions = {
- name: 'horizontal_bar',
- title: i18n.translate('visTypeVislib.horizontalBar.horizontalBarTitle', {
- defaultMessage: 'Horizontal bar',
- }),
- icon: 'visBarHorizontal',
- description: i18n.translate('visTypeVislib.horizontalBar.horizontalBarDescription', {
- defaultMessage: 'Present data in horizontal bars on an axis.',
- }),
- getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush],
+ ...(xyVisTypes.horizontalBar() as BaseVisTypeOptions),
toExpressionAst,
- visConfig: {
- defaults: {
- type: 'histogram',
- grid: {
- categoryLines: false,
- },
- categoryAxes: [
- {
- id: 'CategoryAxis-1',
- type: AxisTypes.CATEGORY,
- position: Positions.LEFT,
- show: true,
- style: {},
- scale: {
- type: ScaleTypes.LINEAR,
- },
- labels: {
- show: true,
- rotate: Rotates.HORIZONTAL,
- filter: false,
- truncate: 200,
- },
- title: {},
- },
- ],
- valueAxes: [
- {
- id: 'ValueAxis-1',
- name: 'LeftAxis-1',
- type: AxisTypes.VALUE,
- position: Positions.BOTTOM,
- show: true,
- style: {},
- scale: {
- type: ScaleTypes.LINEAR,
- mode: AxisModes.NORMAL,
- },
- labels: {
- show: true,
- rotate: Rotates.ANGLED,
- filter: true,
- truncate: 100,
- },
- title: {
- text: countLabel,
- },
- },
- ],
- seriesParams: [
- {
- show: true,
- type: ChartTypes.HISTOGRAM,
- mode: ChartModes.NORMAL,
- data: {
- label: countLabel,
- id: '1',
- },
- valueAxis: 'ValueAxis-1',
- drawLinesBetweenPoints: true,
- lineWidth: 2,
- showCircles: true,
- },
- ],
- addTooltip: true,
- addLegend: true,
- legendPosition: Positions.RIGHT,
- times: [],
- addTimeMarker: false,
- labels: {},
- thresholdLine: {
- show: false,
- value: 10,
- width: 1,
- style: ThresholdLineStyles.FULL,
- color: euiPaletteColorBlind()[9],
- },
- },
- },
- editorConfig: {
- collections: getConfigCollections(),
- optionTabs: getAreaOptionTabs(),
- schemas: new Schemas([
- {
- group: AggGroupNames.Metrics,
- name: 'metric',
- title: i18n.translate('visTypeVislib.horizontalBar.metricTitle', {
- defaultMessage: 'Y-axis',
- }),
- min: 1,
- aggFilter: ['!geo_centroid', '!geo_bounds'],
- defaults: [{ schema: 'metric', type: 'count' }],
- },
- {
- group: AggGroupNames.Metrics,
- name: 'radius',
- title: i18n.translate('visTypeVislib.horizontalBar.radiusTitle', {
- defaultMessage: 'Dot size',
- }),
- min: 0,
- max: 1,
- aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'segment',
- title: i18n.translate('visTypeVislib.horizontalBar.segmentTitle', {
- defaultMessage: 'X-axis',
- }),
- min: 0,
- max: 1,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'group',
- title: i18n.translate('visTypeVislib.horizontalBar.groupTitle', {
- defaultMessage: 'Split series',
- }),
- min: 0,
- max: 3,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'split',
- title: i18n.translate('visTypeVislib.horizontalBar.splitTitle', {
- defaultMessage: 'Split chart',
- }),
- min: 0,
- max: 1,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- ]),
- },
+ visualization: undefined,
};
diff --git a/src/plugins/vis_type_vislib/public/line.ts b/src/plugins/vis_type_vislib/public/line.ts
index ffa40c8c29980..15f20edd359dd 100644
--- a/src/plugins/vis_type_vislib/public/line.ts
+++ b/src/plugins/vis_type_vislib/public/line.ts
@@ -17,164 +17,14 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
-// @ts-ignore
-import { palettes, euiPaletteColorBlind } from '@elastic/eui/lib/services';
+import { xyVisTypes } from '../../vis_type_xy/public';
+import { BaseVisTypeOptions } from '../../visualizations/public';
-import { AggGroupNames } from '../../data/public';
-import { Schemas } from '../../vis_default_editor/public';
-import {
- Positions,
- ChartTypes,
- ChartModes,
- AxisTypes,
- ScaleTypes,
- AxisModes,
- ThresholdLineStyles,
- InterpolationModes,
- getConfigCollections,
-} from './utils/collections';
-import { getAreaOptionTabs, countLabel } from './utils/common_config';
-import { Rotates } from '../../charts/public';
-import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public';
import { toExpressionAst } from './to_ast';
import { BasicVislibParams } from './types';
export const lineVisTypeDefinition: BaseVisTypeOptions = {
- name: 'line',
- title: i18n.translate('visTypeVislib.line.lineTitle', { defaultMessage: 'Line' }),
- icon: 'visLine',
- description: i18n.translate('visTypeVislib.line.lineDescription', {
- defaultMessage: 'Display data as a series of points.',
- }),
- getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush],
+ ...(xyVisTypes.line() as BaseVisTypeOptions),
toExpressionAst,
- visConfig: {
- defaults: {
- type: 'line',
- grid: {
- categoryLines: false,
- },
- categoryAxes: [
- {
- id: 'CategoryAxis-1',
- type: AxisTypes.CATEGORY,
- position: Positions.BOTTOM,
- show: true,
- style: {},
- scale: {
- type: ScaleTypes.LINEAR,
- },
- labels: {
- show: true,
- filter: true,
- truncate: 100,
- },
- title: {},
- },
- ],
- valueAxes: [
- {
- id: 'ValueAxis-1',
- name: 'LeftAxis-1',
- type: AxisTypes.VALUE,
- position: Positions.LEFT,
- show: true,
- style: {},
- scale: {
- type: ScaleTypes.LINEAR,
- mode: AxisModes.NORMAL,
- },
- labels: {
- show: true,
- rotate: Rotates.HORIZONTAL,
- filter: false,
- truncate: 100,
- },
- title: {
- text: countLabel,
- },
- },
- ],
- seriesParams: [
- {
- show: true,
- type: ChartTypes.LINE,
- mode: ChartModes.NORMAL,
- data: {
- label: countLabel,
- id: '1',
- },
- valueAxis: 'ValueAxis-1',
- drawLinesBetweenPoints: true,
- lineWidth: 2,
- interpolate: InterpolationModes.LINEAR,
- showCircles: true,
- },
- ],
- addTooltip: true,
- addLegend: true,
- legendPosition: Positions.RIGHT,
- times: [],
- addTimeMarker: false,
- labels: {},
- thresholdLine: {
- show: false,
- value: 10,
- width: 1,
- style: ThresholdLineStyles.FULL,
- color: euiPaletteColorBlind()[9],
- },
- },
- },
- editorConfig: {
- collections: getConfigCollections(),
- optionTabs: getAreaOptionTabs(),
- schemas: new Schemas([
- {
- group: AggGroupNames.Metrics,
- name: 'metric',
- title: i18n.translate('visTypeVislib.line.metricTitle', { defaultMessage: 'Y-axis' }),
- min: 1,
- aggFilter: ['!geo_centroid', '!geo_bounds'],
- defaults: [{ schema: 'metric', type: 'count' }],
- },
- {
- group: AggGroupNames.Metrics,
- name: 'radius',
- title: i18n.translate('visTypeVislib.line.radiusTitle', { defaultMessage: 'Dot size' }),
- min: 0,
- max: 1,
- aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality', 'top_hits'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'segment',
- title: i18n.translate('visTypeVislib.line.segmentTitle', { defaultMessage: 'X-axis' }),
- min: 0,
- max: 1,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'group',
- title: i18n.translate('visTypeVislib.line.groupTitle', {
- defaultMessage: 'Split series',
- }),
- min: 0,
- max: 3,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'split',
- title: i18n.translate('visTypeVislib.line.splitTitle', {
- defaultMessage: 'Split chart',
- }),
- min: 0,
- max: 1,
- aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
- },
- ]),
- },
+ visualization: undefined,
};
diff --git a/src/plugins/vis_type_vislib/public/pie.ts b/src/plugins/vis_type_vislib/public/pie.ts
index 41b271054d59f..aa5a3ceaaba98 100644
--- a/src/plugins/vis_type_vislib/public/pie.ts
+++ b/src/plugins/vis_type_vislib/public/pie.ts
@@ -18,13 +18,15 @@
*/
import { i18n } from '@kbn/i18n';
+import { Position } from '@elastic/charts';
import { AggGroupNames } from '../../data/public';
import { Schemas } from '../../vis_default_editor/public';
-import { PieOptions } from './components/options';
-import { getPositions, Positions } from './utils/collections';
+import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../visualizations/public';
+import { getPositions } from '../../vis_type_xy/public';
+
import { CommonVislibParams } from './types';
-import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public';
+import { PieOptions } from './editor';
import { toExpressionAst } from './to_ast_pie';
export interface PieVisParams extends CommonVislibParams {
@@ -52,7 +54,7 @@ export const pieVisTypeDefinition: BaseVisTypeOptions = {
type: 'pie',
addTooltip: true,
addLegend: true,
- legendPosition: Positions.RIGHT,
+ legendPosition: Position.Right,
isDonut: true,
labels: {
show: false,
diff --git a/src/plugins/vis_type_vislib/public/pie_fn.ts b/src/plugins/vis_type_vislib/public/pie_fn.ts
index c9da9e9bd9fab..8b16d8eb0982f 100644
--- a/src/plugins/vis_type_vislib/public/pie_fn.ts
+++ b/src/plugins/vis_type_vislib/public/pie_fn.ts
@@ -24,6 +24,7 @@ import { ExpressionFunctionDefinition, Datatable, Render } from '../../expressio
// @ts-ignore
import { vislibSlicesResponseHandler } from './vislib/response_handler';
import { PieVisParams } from './pie';
+import { VislibChartType } from './types';
import { vislibVisName } from './vis_type_vislib_vis_fn';
export const vislibPieName = 'vislib_pie_vis';
@@ -32,9 +33,9 @@ interface Arguments {
visConfig: string;
}
-interface RenderValue {
+export interface PieRenderValue {
+ visType: Extract;
visData: unknown;
- visType: string;
visConfig: PieVisParams;
}
@@ -42,7 +43,7 @@ export type VisTypeVislibPieExpressionFunctionDefinition = ExpressionFunctionDef
typeof vislibPieName,
Datatable,
Arguments,
- Render
+ Render
>;
export const createPieVisFn = (): VisTypeVislibPieExpressionFunctionDefinition => ({
@@ -59,17 +60,21 @@ export const createPieVisFn = (): VisTypeVislibPieExpressionFunctionDefinition =
help: 'vislib pie vis config',
},
},
- fn(input, args) {
+ fn(input, args, handlers) {
const visConfig = JSON.parse(args.visConfig) as PieVisParams;
const visData = vislibSlicesResponseHandler(input, visConfig.dimensions);
+ if (handlers?.inspectorAdapters?.tables) {
+ handlers.inspectorAdapters.tables.logDatatable('default', input);
+ }
+
return {
type: 'render',
as: vislibVisName,
value: {
visData,
visConfig,
- visType: 'pie',
+ visType: VislibChartType.Pie,
},
};
},
diff --git a/src/plugins/vis_type_vislib/public/plugin.ts b/src/plugins/vis_type_vislib/public/plugin.ts
index f183042fd5201..36a184d3da507 100644
--- a/src/plugins/vis_type_vislib/public/plugin.ts
+++ b/src/plugins/vis_type_vislib/public/plugin.ts
@@ -19,25 +19,28 @@
import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/public';
-import { VisTypeXyPluginSetup } from 'src/plugins/vis_type_xy/public';
import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public';
-import { BaseVisTypeOptions, VisualizationsSetup } from '../../visualizations/public';
-import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn';
-import { createPieVisFn } from './pie_fn';
-import { visLibVisTypeDefinitions, pieVisTypeDefinition } from './vis_type_vislib_vis_types';
+import { VisualizationsSetup } from '../../visualizations/public';
import { ChartsPluginSetup } from '../../charts/public';
import { DataPublicPluginStart } from '../../data/public';
import { KibanaLegacyStart } from '../../kibana_legacy/public';
+import { LEGACY_CHARTS_LIBRARY } from '../../vis_type_xy/public';
+
+import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn';
+import { createPieVisFn } from './pie_fn';
+import {
+ convertedTypeDefinitions,
+ pieVisTypeDefinition,
+ visLibVisTypeDefinitions,
+} from './vis_type_vislib_vis_types';
import { setFormatService, setDataActions } from './services';
import { getVislibVisRenderer } from './vis_renderer';
-import { BasicVislibParams } from './types';
/** @internal */
export interface VisTypeVislibPluginSetupDependencies {
expressions: ReturnType;
visualizations: VisualizationsSetup;
charts: ChartsPluginSetup;
- visTypeXy?: VisTypeXyPluginSetup;
}
/** @internal */
@@ -56,23 +59,21 @@ export class VisTypeVislibPlugin
public async setup(
core: VisTypeVislibCoreSetup,
- { expressions, visualizations, charts, visTypeXy }: VisTypeVislibPluginSetupDependencies
+ { expressions, visualizations, charts }: VisTypeVislibPluginSetupDependencies
) {
- // if visTypeXy plugin is disabled it's config will be undefined
- if (!visTypeXy) {
- const convertedTypes: Array> = [];
- const convertedFns: any[] = [];
-
- // Register legacy vislib types that have been converted
- convertedFns.forEach(expressions.registerFunction);
- convertedTypes.forEach(visualizations.createBaseVisualization);
+ if (!core.uiSettings.get(LEGACY_CHARTS_LIBRARY, true)) {
+ // Register only non-replaced vis types
+ convertedTypeDefinitions.forEach(visualizations.createBaseVisualization);
+ visualizations.createBaseVisualization(pieVisTypeDefinition);
+ expressions.registerRenderer(getVislibVisRenderer(core, charts));
+ [createVisTypeVislibVisFn(), createPieVisFn()].forEach(expressions.registerFunction);
+ } else {
+ // Register all vis types
+ visLibVisTypeDefinitions.forEach(visualizations.createBaseVisualization);
+ visualizations.createBaseVisualization(pieVisTypeDefinition);
expressions.registerRenderer(getVislibVisRenderer(core, charts));
+ [createVisTypeVislibVisFn(), createPieVisFn()].forEach(expressions.registerFunction);
}
- // Register non-converted types
- visLibVisTypeDefinitions.forEach(visualizations.createBaseVisualization);
- visualizations.createBaseVisualization(pieVisTypeDefinition);
- expressions.registerRenderer(getVislibVisRenderer(core, charts));
- [createVisTypeVislibVisFn(), createPieVisFn()].forEach(expressions.registerFunction);
}
public start(core: CoreStart, { data }: VisTypeVislibPluginStartDependencies) {
diff --git a/src/plugins/vis_type_vislib/public/to_ast.ts b/src/plugins/vis_type_vislib/public/to_ast.ts
index 3a05410ff006b..30ed2e4ca1bb4 100644
--- a/src/plugins/vis_type_vislib/public/to_ast.ts
+++ b/src/plugins/vis_type_vislib/public/to_ast.ts
@@ -21,14 +21,11 @@ import moment from 'moment';
import { VisToExpressionAst, getVisSchemas } from '../../visualizations/public';
import { buildExpression, buildExpressionFunction } from '../../expressions/public';
+import type { Dimensions, DateHistogramParams, HistogramParams } from '../../vis_type_xy/public';
+import { BUCKET_TYPES } from '../../data/public';
import { vislibVisName, VisTypeVislibExpressionFunctionDefinition } from './vis_type_vislib_vis_fn';
-import { BasicVislibParams } from './types';
-import {
- DateHistogramParams,
- Dimensions,
- HistogramParams,
-} from './vislib/helpers/point_series/point_series';
+import { BasicVislibParams, VislibChartType } from './types';
import { getEsaggsFn } from './to_ast_esaggs';
export const toExpressionAst: VisToExpressionAst = async (vis, params) => {
@@ -47,7 +44,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis
if (dimensions.x) {
const xAgg = responseAggs[dimensions.x.accessor] as any;
- if (xAgg.type.name === 'date_histogram') {
+ if (xAgg.type.name === BUCKET_TYPES.DATE_HISTOGRAM) {
(dimensions.x.params as DateHistogramParams).date = true;
const { esUnit, esValue } = xAgg.buckets.getInterval();
(dimensions.x.params as DateHistogramParams).intervalESUnit = esUnit;
@@ -57,7 +54,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis
.asMilliseconds();
(dimensions.x.params as DateHistogramParams).format = xAgg.buckets.getScaledDateFormat();
(dimensions.x.params as DateHistogramParams).bounds = xAgg.buckets.getBounds();
- } else if (xAgg.type.name === 'histogram') {
+ } else if (xAgg.type.name === BUCKET_TYPES.HISTOGRAM) {
const intervalParam = xAgg.type.paramByName('interval');
const output = { params: {} as any };
await intervalParam.modifyAggConfigOnSearchRequestStart(xAgg, vis.data.searchSource, {
@@ -88,15 +85,15 @@ export const toExpressionAst: VisToExpressionAst = async (vis
visConfig.dimensions = dimensions;
- const visTypeXy = buildExpressionFunction(
+ const visTypeVislib = buildExpressionFunction(
vislibVisName,
{
- type: vis.type.name,
+ type: vis.type.name as Exclude,
visConfig: JSON.stringify(visConfig),
}
);
- const ast = buildExpression([getEsaggsFn(vis), visTypeXy]);
+ const ast = buildExpression([getEsaggsFn(vis), visTypeVislib]);
return ast.toAst();
};
diff --git a/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts b/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts
index 2835e5cc1c255..d23f1ab3626d3 100644
--- a/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts
+++ b/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts
@@ -29,6 +29,8 @@ import { BasicVislibParams } from './types';
/**
* Get esaggs expressions function
+ * TODO: replace this with vis.data.aggs!.toExpressionAst();
+ * https://github.com/elastic/kibana/issues/61768
* @param vis
*/
export function getEsaggsFn(vis: Vis | Vis) {
diff --git a/src/plugins/vis_type_vislib/public/types.ts b/src/plugins/vis_type_vislib/public/types.ts
index c0311edf76154..4f6c427669324 100644
--- a/src/plugins/vis_type_vislib/public/types.ts
+++ b/src/plugins/vis_type_vislib/public/types.ts
@@ -17,87 +17,71 @@
* under the License.
*/
-import { TimeMarker } from './vislib/visualizations/time_marker';
+import { $Values } from '@kbn/utility-types';
+import { Position } from '@elastic/charts';
+
+import { Labels } from '../../charts/public';
import {
- Positions,
- ChartModes,
- ChartTypes,
- AxisModes,
- AxisTypes,
- InterpolationModes,
- ScaleTypes,
- ThresholdLineStyles,
-} from './utils/collections';
-import { Labels, Style } from '../../charts/public';
-import { Dimensions } from './vislib/helpers/point_series/point_series';
+ CategoryAxis,
+ Dimensions,
+ Grid,
+ SeriesParam,
+ ThresholdLine,
+ ValueAxis,
+} from '../../vis_type_xy/public';
+import { TimeMarker } from './vislib/visualizations/time_marker';
+
+/**
+ * Gauge title alignment
+ */
+export const Alignment = Object.freeze({
+ Automatic: 'automatic' as const,
+ Horizontal: 'horizontal' as const,
+ Vertical: 'vertical' as const,
+});
+export type Alignment = $Values;
+
+export const GaugeType = Object.freeze({
+ Arc: 'Arc' as const,
+ Circle: 'Circle' as const,
+});
+export type GaugeType = $Values;
+
+export const VislibChartType = Object.freeze({
+ Histogram: 'histogram' as const,
+ HorizontalBar: 'horizontal_bar' as const,
+ Line: 'line' as const,
+ Pie: 'pie' as const,
+ Area: 'area' as const,
+ PointSeries: 'point_series' as const,
+ Heatmap: 'heatmap' as const,
+ Gauge: 'gauge' as const,
+ Goal: 'goal' as const,
+ Metric: 'metric' as const,
+});
+export type VislibChartType = $Values;
export interface CommonVislibParams {
addTooltip: boolean;
addLegend: boolean;
- legendPosition: Positions;
+ legendPosition: Position;
dimensions: Dimensions;
}
-export interface Scale {
- boundsMargin?: number | '';
- defaultYExtents?: boolean;
- max?: number | null;
- min?: number | null;
- mode?: AxisModes;
- setYExtents?: boolean;
- type: ScaleTypes;
-}
-
-interface ThresholdLine {
- show: boolean;
- value: number | null;
- width: number | null;
- style: ThresholdLineStyles;
- color: string;
-}
-
-export interface Axis {
- id: string;
- labels: Labels;
- position: Positions;
- scale: Scale;
- show: boolean;
- style: Style;
- title: { text: string };
- type: AxisTypes;
-}
-
-export interface ValueAxis extends Axis {
- name: string;
-}
-
-export interface SeriesParam {
- data: { label: string; id: string };
- drawLinesBetweenPoints: boolean;
- interpolate: InterpolationModes;
- lineWidth?: number;
- mode: ChartModes;
- show: boolean;
- showCircles: boolean;
- type: ChartTypes;
- valueAxis: string;
-}
-
export interface BasicVislibParams extends CommonVislibParams {
+ type: VislibChartType;
+ addLegend: boolean;
addTimeMarker: boolean;
- categoryAxes: Axis[];
+ categoryAxes: CategoryAxis[];
orderBucketsBySum?: boolean;
labels: Labels;
thresholdLine: ThresholdLine;
valueAxes: ValueAxis[];
+ grid: Grid;
gauge?: {
percentageMode: boolean;
};
- grid: {
- categoryLines: boolean;
- valueAxis?: string;
- };
seriesParams: SeriesParam[];
times: TimeMarker[];
- type: string;
+ radiusRatio: number;
}
diff --git a/src/plugins/vis_type_vislib/public/utils/collections.ts b/src/plugins/vis_type_vislib/public/utils/collections.ts
deleted file mode 100644
index 44df4864bfd68..0000000000000
--- a/src/plugins/vis_type_vislib/public/utils/collections.ts
+++ /dev/null
@@ -1,338 +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 { i18n } from '@kbn/i18n';
-import { $Values } from '@kbn/utility-types';
-
-import { colorSchemas, Rotates } from '../../../charts/public';
-
-export const Positions = Object.freeze({
- RIGHT: 'right' as 'right',
- LEFT: 'left' as 'left',
- TOP: 'top' as 'top',
- BOTTOM: 'bottom' as 'bottom',
-});
-export type Positions = $Values;
-
-const getPositions = () => [
- {
- text: i18n.translate('visTypeVislib.legendPositions.topText', {
- defaultMessage: 'Top',
- }),
- value: Positions.TOP,
- },
- {
- text: i18n.translate('visTypeVislib.legendPositions.leftText', {
- defaultMessage: 'Left',
- }),
- value: Positions.LEFT,
- },
- {
- text: i18n.translate('visTypeVislib.legendPositions.rightText', {
- defaultMessage: 'Right',
- }),
- value: Positions.RIGHT,
- },
- {
- text: i18n.translate('visTypeVislib.legendPositions.bottomText', {
- defaultMessage: 'Bottom',
- }),
- value: Positions.BOTTOM,
- },
-];
-
-export const ChartTypes = Object.freeze({
- LINE: 'line' as 'line',
- AREA: 'area' as 'area',
- HISTOGRAM: 'histogram' as 'histogram',
-});
-export type ChartTypes = $Values;
-
-const getChartTypes = () => [
- {
- text: i18n.translate('visTypeVislib.chartTypes.lineText', {
- defaultMessage: 'Line',
- }),
- value: ChartTypes.LINE,
- },
- {
- text: i18n.translate('visTypeVislib.chartTypes.areaText', {
- defaultMessage: 'Area',
- }),
- value: ChartTypes.AREA,
- },
- {
- text: i18n.translate('visTypeVislib.chartTypes.barText', {
- defaultMessage: 'Bar',
- }),
- value: ChartTypes.HISTOGRAM,
- },
-];
-
-export const ChartModes = Object.freeze({
- NORMAL: 'normal' as 'normal',
- STACKED: 'stacked' as 'stacked',
-});
-export type ChartModes = $Values;
-
-const getChartModes = () => [
- {
- text: i18n.translate('visTypeVislib.chartModes.normalText', {
- defaultMessage: 'Normal',
- }),
- value: ChartModes.NORMAL,
- },
- {
- text: i18n.translate('visTypeVislib.chartModes.stackedText', {
- defaultMessage: 'Stacked',
- }),
- value: ChartModes.STACKED,
- },
-];
-
-export const InterpolationModes = Object.freeze({
- LINEAR: 'linear' as 'linear',
- CARDINAL: 'cardinal' as 'cardinal',
- STEP_AFTER: 'step-after' as 'step-after',
-});
-export type InterpolationModes = $Values;
-
-const getInterpolationModes = () => [
- {
- text: i18n.translate('visTypeVislib.interpolationModes.straightText', {
- defaultMessage: 'Straight',
- }),
- value: InterpolationModes.LINEAR,
- },
- {
- text: i18n.translate('visTypeVislib.interpolationModes.smoothedText', {
- defaultMessage: 'Smoothed',
- }),
- value: InterpolationModes.CARDINAL,
- },
- {
- text: i18n.translate('visTypeVislib.interpolationModes.steppedText', {
- defaultMessage: 'Stepped',
- }),
- value: InterpolationModes.STEP_AFTER,
- },
-];
-
-export const AxisTypes = Object.freeze({
- CATEGORY: 'category' as 'category',
- VALUE: 'value' as 'value',
-});
-export type AxisTypes = $Values;
-
-export const ScaleTypes = Object.freeze({
- LINEAR: 'linear' as 'linear',
- LOG: 'log' as 'log',
- SQUARE_ROOT: 'square root' as 'square root',
-});
-export type ScaleTypes = $Values;
-
-const getScaleTypes = () => [
- {
- text: i18n.translate('visTypeVislib.scaleTypes.linearText', {
- defaultMessage: 'Linear',
- }),
- value: ScaleTypes.LINEAR,
- },
- {
- text: i18n.translate('visTypeVislib.scaleTypes.logText', {
- defaultMessage: 'Log',
- }),
- value: ScaleTypes.LOG,
- },
- {
- text: i18n.translate('visTypeVislib.scaleTypes.squareRootText', {
- defaultMessage: 'Square root',
- }),
- value: ScaleTypes.SQUARE_ROOT,
- },
-];
-
-export const AxisModes = Object.freeze({
- NORMAL: 'normal' as 'normal',
- PERCENTAGE: 'percentage' as 'percentage',
- WIGGLE: 'wiggle' as 'wiggle',
- SILHOUETTE: 'silhouette' as 'silhouette',
-});
-export type AxisModes = $Values;
-
-const getAxisModes = () => [
- {
- text: i18n.translate('visTypeVislib.axisModes.normalText', {
- defaultMessage: 'Normal',
- }),
- value: AxisModes.NORMAL,
- },
- {
- text: i18n.translate('visTypeVislib.axisModes.percentageText', {
- defaultMessage: 'Percentage',
- }),
- value: AxisModes.PERCENTAGE,
- },
- {
- text: i18n.translate('visTypeVislib.axisModes.wiggleText', {
- defaultMessage: 'Wiggle',
- }),
- value: AxisModes.WIGGLE,
- },
- {
- text: i18n.translate('visTypeVislib.axisModes.silhouetteText', {
- defaultMessage: 'Silhouette',
- }),
- value: AxisModes.SILHOUETTE,
- },
-];
-
-export const ThresholdLineStyles = Object.freeze({
- FULL: 'full' as 'full',
- DASHED: 'dashed' as 'dashed',
- DOT_DASHED: 'dot-dashed' as 'dot-dashed',
-});
-export type ThresholdLineStyles = $Values;
-
-const getThresholdLineStyles = () => [
- {
- value: ThresholdLineStyles.FULL,
- text: i18n.translate('visTypeVislib.thresholdLine.style.fullText', {
- defaultMessage: 'Full',
- }),
- },
- {
- value: ThresholdLineStyles.DASHED,
- text: i18n.translate('visTypeVislib.thresholdLine.style.dashedText', {
- defaultMessage: 'Dashed',
- }),
- },
- {
- value: ThresholdLineStyles.DOT_DASHED,
- text: i18n.translate('visTypeVislib.thresholdLine.style.dotdashedText', {
- defaultMessage: 'Dot-dashed',
- }),
- },
-];
-
-const getRotateOptions = () => [
- {
- text: i18n.translate('visTypeVislib.categoryAxis.rotate.horizontalText', {
- defaultMessage: 'Horizontal',
- }),
- value: Rotates.HORIZONTAL,
- },
- {
- text: i18n.translate('visTypeVislib.categoryAxis.rotate.verticalText', {
- defaultMessage: 'Vertical',
- }),
- value: Rotates.VERTICAL,
- },
- {
- text: i18n.translate('visTypeVislib.categoryAxis.rotate.angledText', {
- defaultMessage: 'Angled',
- }),
- value: Rotates.ANGLED,
- },
-];
-
-export const GaugeTypes = Object.freeze({
- ARC: 'Arc' as 'Arc',
- CIRCLE: 'Circle' as 'Circle',
-});
-export type GaugeTypes = $Values;
-
-const getGaugeTypes = () => [
- {
- text: i18n.translate('visTypeVislib.gauge.gaugeTypes.arcText', {
- defaultMessage: 'Arc',
- }),
- value: GaugeTypes.ARC,
- },
- {
- text: i18n.translate('visTypeVislib.gauge.gaugeTypes.circleText', {
- defaultMessage: 'Circle',
- }),
- value: GaugeTypes.CIRCLE,
- },
-];
-
-export const Alignments = Object.freeze({
- AUTOMATIC: 'automatic' as 'automatic',
- HORIZONTAL: 'horizontal' as 'horizontal',
- VERTICAL: 'vertical' as 'vertical',
-});
-export type Alignments = $Values;
-
-const getAlignments = () => [
- {
- text: i18n.translate('visTypeVislib.gauge.alignmentAutomaticTitle', {
- defaultMessage: 'Automatic',
- }),
- value: Alignments.AUTOMATIC,
- },
- {
- text: i18n.translate('visTypeVislib.gauge.alignmentHorizontalTitle', {
- defaultMessage: 'Horizontal',
- }),
- value: Alignments.HORIZONTAL,
- },
- {
- text: i18n.translate('visTypeVislib.gauge.alignmentVerticalTitle', {
- defaultMessage: 'Vertical',
- }),
- value: Alignments.VERTICAL,
- },
-];
-
-const getConfigCollections = () => ({
- legendPositions: getPositions(),
- positions: getPositions(),
- chartTypes: getChartTypes(),
- axisModes: getAxisModes(),
- scaleTypes: getScaleTypes(),
- chartModes: getChartModes(),
- interpolationModes: getInterpolationModes(),
- thresholdLineStyles: getThresholdLineStyles(),
-});
-
-const getGaugeCollections = () => ({
- gaugeTypes: getGaugeTypes(),
- alignments: getAlignments(),
- colorSchemas,
-});
-
-const getHeatmapCollections = () => ({
- legendPositions: getPositions(),
- scales: getScaleTypes(),
- colorSchemas,
-});
-
-export {
- getConfigCollections,
- getGaugeCollections,
- getHeatmapCollections,
- getPositions,
- getRotateOptions,
- getScaleTypes,
- getInterpolationModes,
- getChartTypes,
- getChartModes,
- getAxisModes,
-};
diff --git a/src/plugins/vis_type_vislib/public/vis_controller.tsx b/src/plugins/vis_type_vislib/public/vis_controller.tsx
index 1804d0d52ae7a..2a32d19874c22 100644
--- a/src/plugins/vis_type_vislib/public/vis_controller.tsx
+++ b/src/plugins/vis_type_vislib/public/vis_controller.tsx
@@ -22,7 +22,7 @@ import React, { RefObject } from 'react';
import { mountReactNode } from '../../../core/public/utils';
import { ChartsPluginSetup } from '../../charts/public';
-import { PersistedState } from '../../visualizations/public';
+import type { PersistedState } from '../../visualizations/public';
import { IInterpreterRenderHandlers } from '../../expressions/public';
import { VisTypeVislibCoreSetup } from './plugin';
@@ -115,7 +115,7 @@ export const createVislibVisController = (
})
.addClass((legendClassName as any)[visParams.legendPosition]);
- this.mountLegend(esResponse, visParams, fireEvent, uiState);
+ this.mountLegend(esResponse, visParams, fireEvent, uiState as PersistedState);
}
this.vislibVis.render(esResponse, uiState);
@@ -128,7 +128,7 @@ export const createVislibVisController = (
CUSTOM_LEGEND_VIS_TYPES.includes(this.vislibVis.visConfigArgs.type)
) {
this.unmountLegend?.();
- this.mountLegend(esResponse, visParams, fireEvent, uiState);
+ this.mountLegend(esResponse, visParams, fireEvent, uiState as PersistedState);
this.vislibVis.render(esResponse, uiState);
}
}
diff --git a/src/plugins/vis_type_vislib/public/vis_renderer.tsx b/src/plugins/vis_type_vislib/public/vis_renderer.tsx
index 9c697f481e63e..205c22092ac61 100644
--- a/src/plugins/vis_type_vislib/public/vis_renderer.tsx
+++ b/src/plugins/vis_type_vislib/public/vis_renderer.tsx
@@ -26,9 +26,13 @@ import { ChartsPluginSetup } from '../../charts/public';
import { VisTypeVislibCoreSetup } from './plugin';
import { VislibRenderValue, vislibVisName } from './vis_type_vislib_vis_fn';
+import { VislibChartType } from './types';
+import { PieRenderValue } from './pie_fn';
-function shouldShowNoResultsMessage(visData: any, visType: string): boolean {
- if (['goal', 'gauge'].includes(visType)) {
+const VislibWrapper = lazy(() => import('./vis_wrapper'));
+
+function shouldShowNoResultsMessage(visData: any, visType: VislibChartType): boolean {
+ if (['goal', 'gauge'].includes(visType as string)) {
return false;
}
@@ -38,13 +42,12 @@ function shouldShowNoResultsMessage(visData: any, visType: string): boolean {
return Boolean(isZeroHits);
}
-const VislibWrapper = lazy(() => import('./vis_wrapper'));
-
export const getVislibVisRenderer: (
core: VisTypeVislibCoreSetup,
charts: ChartsPluginSetup
-) => ExpressionRenderDefinition = (core, charts) => ({
+) => ExpressionRenderDefinition = (core, charts) => ({
name: vislibVisName,
+ displayName: 'Vislib visualization',
reuseDomNode: true,
render: async (domNode, config, handlers) => {
const showNoResult = shouldShowNoResultsMessage(config.visData, config.visType);
diff --git a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts
index c5fa8f36f43e3..d627b8587882a 100644
--- a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts
+++ b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts
@@ -23,18 +23,18 @@ import { ExpressionFunctionDefinition, Datatable, Render } from '../../expressio
// @ts-ignore
import { vislibSeriesResponseHandler } from './vislib/response_handler';
-import { BasicVislibParams } from './types';
+import { BasicVislibParams, VislibChartType } from './types';
export const vislibVisName = 'vislib_vis';
interface Arguments {
- type: string;
+ type: Exclude;
visConfig: string;
}
export interface VislibRenderValue {
- visData: any;
- visType: string;
+ visType: Exclude;
+ visData: unknown;
visConfig: BasicVislibParams;
}
@@ -64,11 +64,15 @@ export const createVisTypeVislibVisFn = (): VisTypeVislibExpressionFunctionDefin
help: 'vislib vis config',
},
},
- fn(context, args) {
- const visType = args.type;
+ fn(context, args, handlers) {
+ const visType = args.type as Exclude;
const visConfig = JSON.parse(args.visConfig) as BasicVislibParams;
const visData = vislibSeriesResponseHandler(context, visConfig.dimensions);
+ if (handlers?.inspectorAdapters?.tables) {
+ handlers.inspectorAdapters.tables.logDatatable('default', context);
+ }
+
return {
type: 'render',
as: vislibVisName,
diff --git a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts
index 1b43a213c618d..28415e3e2fa8c 100644
--- a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts
+++ b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts
@@ -36,3 +36,9 @@ export const visLibVisTypeDefinitions = [
gaugeVisTypeDefinition,
goalVisTypeDefinition,
];
+
+export const convertedTypeDefinitions = [
+ heatmapVisTypeDefinition,
+ gaugeVisTypeDefinition,
+ goalVisTypeDefinition,
+];
diff --git a/src/plugins/vis_type_vislib/public/vis_wrapper.tsx b/src/plugins/vis_type_vislib/public/vis_wrapper.tsx
index 980ba1c175885..b8dbd0f945c32 100644
--- a/src/plugins/vis_type_vislib/public/vis_wrapper.tsx
+++ b/src/plugins/vis_type_vislib/public/vis_wrapper.tsx
@@ -22,15 +22,17 @@ import { EuiResizeObserver } from '@elastic/eui';
import { debounce } from 'lodash';
import { IInterpreterRenderHandlers } from '../../expressions/public';
+import type { PersistedState } from '../../visualizations/public';
import { ChartsPluginSetup } from '../../charts/public';
import { VislibRenderValue } from './vis_type_vislib_vis_fn';
import { createVislibVisController, VislibVisController } from './vis_controller';
import { VisTypeVislibCoreSetup } from './plugin';
+import { PieRenderValue } from './pie_fn';
import './index.scss';
-type VislibWrapperProps = VislibRenderValue & {
+type VislibWrapperProps = (VislibRenderValue | PieRenderValue) & {
core: VisTypeVislibCoreSetup;
charts: ChartsPluginSetup;
handlers: IInterpreterRenderHandlers;
@@ -65,10 +67,12 @@ const VislibWrapper = ({ core, charts, visData, visConfig, handlers }: VislibWra
useEffect(() => {
if (handlers.uiState) {
- handlers.uiState.on('change', updateChart);
+ const uiState = handlers.uiState as PersistedState;
+
+ uiState.on('change', updateChart);
return () => {
- handlers.uiState?.off('change', updateChart);
+ uiState?.off('change', updateChart);
};
}
}, [handlers.uiState, updateChart]);
diff --git a/src/plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss b/src/plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss
index a06f0cb00787b..cb63811800c2d 100644
--- a/src/plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss
+++ b/src/plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss
@@ -3,8 +3,6 @@
// NOTE: Some of the styles attempt to align with the TSVB legend
$visLegendWidth: 150px;
-$visColorPickerWidth: $euiSizeM * 10;
-$visLegendLineHeight: $euiSize;
.visLegend__toggle {
border-radius: $euiBorderRadius;
@@ -81,20 +79,3 @@ $visLegendLineHeight: $euiSize;
visibility: hidden;
}
}
-
-.visLegend__valueColorPicker {
- width: ($euiSizeL * 8); // 8 columns
-}
-
-.visLegend__valueColorPickerDot {
- cursor: pointer;
-
- &:hover {
- transform: scale(1.4);
- }
-
- &-isSelected {
- border: $euiSizeXS solid;
- border-radius: 100%;
- }
-}
diff --git a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx
index 7acc97404c11c..5b1a2b3975367 100644
--- a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx
+++ b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx
@@ -243,7 +243,7 @@ describe('VisLegend Component', () => {
const first = getLegendItems(wrapper).first();
first.simulate('click');
- expect(wrapper.exists('.visLegend__valueDetails')).toBe(true);
+ expect(wrapper.exists('.visColorPicker')).toBe(true);
});
});
@@ -256,8 +256,8 @@ describe('VisLegend Component', () => {
const first = getLegendItems(wrapper).first();
first.simulate('click');
- const popover = wrapper.find('.visLegend__valueDetails').first();
- const firstColor = popover.find('.visLegend__valueColorPickerDot').first();
+ const popover = wrapper.find('.visColorPicker').first();
+ const firstColor = popover.find('.visColorPicker__valueDot').first();
firstColor.simulate('click');
const colors = mockState.get('vis.colors');
diff --git a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx
index cec97f0cadf11..5065642d88c6b 100644
--- a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx
+++ b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx
@@ -78,18 +78,20 @@ export class VisLegend extends PureComponent {
});
};
- setColor = (label: string, color: string) => (event: BaseSyntheticEvent) => {
+ setColor = (label: string | number, color: string | null, event: BaseSyntheticEvent) => {
if ((event as KeyboardEvent).key && (event as KeyboardEvent).key !== keys.ENTER) {
return;
}
- const colors = this.props.uiState?.get('vis.colors') || {};
- if (colors[label] === color) delete colors[label];
- else colors[label] = color;
- this.props.uiState?.setSilent('vis.colors', null);
- this.props.uiState?.set('vis.colors', colors);
- this.props.uiState?.emit('colorChanged');
- this.refresh();
+ this.setState({ selectedLabel: null }, () => {
+ const colors = this.props.uiState?.get('vis.colors') || {};
+ if (colors[label] === color || !color) delete colors[label];
+ else colors[label] = color;
+ this.props.uiState?.setSilent('vis.colors', null);
+ this.props.uiState?.set('vis.colors', colors);
+ this.props.uiState?.emit('colorChanged');
+ this.refresh();
+ });
};
filter = ({ values: data }: LegendItem, negate: boolean) => {
diff --git a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx
index 39e6fb2d2aff4..6c7e343a22d8f 100644
--- a/src/plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx
+++ b/src/plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx
@@ -18,10 +18,8 @@
*/
import React, { memo, useState, BaseSyntheticEvent, KeyboardEvent } from 'react';
-import classNames from 'classnames';
import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiPopover,
keys,
@@ -33,7 +31,8 @@ import {
EuiButtonGroupOptionProps,
} from '@elastic/eui';
-import { legendColors, LegendItem } from './models';
+import { LegendItem } from './models';
+import { ColorPicker } from '../../../../../charts/public';
interface Props {
item: LegendItem;
@@ -45,7 +44,7 @@ interface Props {
onSelect: (label: string | null) => (event?: BaseSyntheticEvent) => void;
onHighlight: (event: BaseSyntheticEvent) => void;
onUnhighlight: (event: BaseSyntheticEvent) => void;
- setColor: (label: string, color: string) => (event: BaseSyntheticEvent) => void;
+ setColor: (label: string, color: string | null, event: BaseSyntheticEvent) => void;
getColor: (label: string) => string;
}
@@ -159,40 +158,14 @@ const VisLegendItemComponent = ({
closePopover={onSelect(null)}
panelPaddingSize="s"
>
-
- {canFilter && renderFilterBar()}
+ {canFilter && renderFilterBar()}
-
-
-
-
- {legendColors.map((color) => (
-
- ))}
-
-
+ setColor(item.label, c, e)}
+ />
);
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts
index ae6b365efc0cd..1b51fb8a53d11 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts
@@ -17,9 +17,10 @@
* under the License.
*/
+import type { Dimension } from '../../../../../vis_type_xy/public';
+
import { addToSiri, Serie } from './_add_to_siri';
import { Point } from './_get_point';
-import { Dimension } from './point_series';
describe('addToSiri', function () {
it('creates a new series the first time it sees an id', function () {
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts
index 5e5185d6c31ab..2e04e916e85f2 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts
@@ -17,8 +17,10 @@
* under the License.
*/
+import { getAggId } from '../../../../../vis_type_xy/public';
+import type { Dimension } from '../../../../../vis_type_xy/public';
+
import { Point } from './_get_point';
-import { Dimension } from './point_series';
export interface Serie {
id: string;
@@ -48,7 +50,7 @@ export function addToSiri(
}
series.set(id, {
- id: id.split('-').pop() as string,
+ id: getAggId(id),
rawId: id,
label: yLabel == null ? id : yLabel,
count: 0,
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts
index fb14b04357f8f..5efde63427573 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts
@@ -17,8 +17,10 @@
* under the License.
*/
+import type { Dimension, Dimensions } from '../../../../../vis_type_xy/public';
+
import { getAspects } from './_get_aspects';
-import { Dimension, Dimensions, Aspect } from './point_series';
+import { Aspect } from './point_series';
import { Table, Row } from '../../types';
describe('getAspects', function () {
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts
index 87819aa9b2a5c..e4094a4549841 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts
@@ -17,8 +17,10 @@
* under the License.
*/
+import type { Dimensions } from '../../../../../vis_type_xy/public';
+
import { makeFakeXAspect } from './_fake_x_aspect';
-import { Dimensions, Aspects } from './point_series';
+import { Aspects } from './point_series';
import { Table } from '../../types';
/**
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts
index be44975bd4eb0..03d41096a8c6f 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts
@@ -18,6 +18,7 @@
*/
import { IFieldFormatsRegistry } from '../../../../../data/common';
+
import { getPoint } from './_get_point';
import { setFormatService } from '../../../services';
import { Aspect } from './point_series';
@@ -94,7 +95,12 @@ describe('getPoint', function () {
it('should call deserialize', function () {
const seriesAspect = [
- { accessor: '1', format: { id: 'number', params: { pattern: '$' } } } as Aspect,
+ {
+ title: 'series',
+ accessor: '1',
+ format: { id: 'number', params: { pattern: '$' } },
+ params: {},
+ } as Aspect,
];
getPoint(table, xAspect, seriesAspect, row, 0, yAspect);
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.ts
index 5eb1e65965318..fb42416abe249 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.ts
@@ -41,7 +41,7 @@ export interface Point {
table: Table;
column: number;
row: number;
- value: number;
+ value: string;
title: string;
};
parent: Aspect | null;
@@ -94,7 +94,7 @@ export function getPoint(
table: table.$parent.table,
column: table.$parent.column,
row: table.$parent.row,
- value: table.$parent.key,
+ value: table.$parent.formattedKey,
title: table.$parent.name,
},
parent: series ? series[0] : null,
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts
index 3f0560c2c9f28..aa24530b025dc 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts
@@ -18,16 +18,12 @@
*/
import moment from 'moment';
+
+import type { DateHistogramParams, HistogramParams } from '../../../../../vis_type_xy/public';
+
import { initXAxis } from './_init_x_axis';
import { makeFakeXAspect } from './_fake_x_aspect';
-import {
- Aspects,
- Chart,
- DateHistogramOrdered,
- DateHistogramParams,
- HistogramOrdered,
- HistogramParams,
-} from './point_series';
+import { Aspects, Chart, DateHistogramOrdered, HistogramOrdered } from './point_series';
import { Table, Column } from '../../types';
describe('initXAxis', function () {
@@ -110,7 +106,7 @@ describe('initXAxis', function () {
it('reads the date interval param from the x agg', function () {
const dateHistogramParams = chart.aspects.x[0].params as DateHistogramParams;
- dateHistogramParams.interval = 'P1D';
+ dateHistogramParams.interval = moment.duration(1, 'd').asMilliseconds();
dateHistogramParams.intervalESValue = 1;
dateHistogramParams.intervalESUnit = 'd';
dateHistogramParams.date = true;
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts
index b2e4d6e4b40c9..7dd1dd259f785 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts
@@ -19,8 +19,11 @@
import moment from 'moment';
import _ from 'lodash';
+
+import type { DateHistogramParams } from '../../../../../vis_type_xy/public/types';
+
import { orderedDateAxis } from './_ordered_date_axis';
-import { DateHistogramParams, OrderedChart } from './point_series';
+import { OrderedChart } from './point_series';
describe('orderedDateAxis', function () {
const baseArgs = {
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts
index 2a5ab197c9ab7..7c343af7840ee 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts
@@ -18,7 +18,10 @@
*/
import _ from 'lodash';
-import { buildPointSeriesData, Dimensions } from './point_series';
+
+import type { Dimensions } from '../../../../../vis_type_xy/public';
+
+import { buildPointSeriesData } from './point_series';
import { Table, Column } from '../../types';
import { setFormatService } from '../../../services';
import { Serie } from './_add_to_siri';
diff --git a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts
index f40d01e6a8123..2bc669e0b77a3 100644
--- a/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts
@@ -18,6 +18,14 @@
*/
import { Duration } from 'moment';
+
+import type {
+ Dimension,
+ Dimensions,
+ DateHistogramParams,
+ HistogramParams,
+} from '../../../../../vis_type_xy/public';
+
import { getSeries } from './_get_series';
import { getAspects } from './_get_aspects';
import { initYAxis } from './_init_y_axis';
@@ -26,41 +34,6 @@ import { orderedDateAxis } from './_ordered_date_axis';
import { Serie } from './_add_to_siri';
import { Column, Table } from '../../types';
-export interface DateHistogramParams {
- date: boolean;
- interval: number | string;
- intervalESValue: number;
- intervalESUnit: string;
- format: string;
- bounds?: {
- min: string | number;
- max: string | number;
- };
-}
-export interface HistogramParams {
- interval: number;
-}
-export interface FakeParams {
- defaultValue: string;
-}
-export interface Dimension {
- accessor: number;
- format: {
- id?: string;
- params?: { pattern?: string; [key: string]: any };
- };
- params: DateHistogramParams | HistogramParams | FakeParams | {};
-}
-
-export interface Dimensions {
- x: Dimension | null;
- y: Dimension[];
- z?: Dimension[];
- series?: Dimension | Dimension[];
- width?: Dimension[];
- splitRow?: Dimension[];
- splitColumn?: Dimension[];
-}
export interface Aspect {
accessor: Column['id'];
column?: Dimension['accessor'];
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/handler.js b/src/plugins/vis_type_vislib/public/vislib/lib/handler.js
index 938ea3adcb9b5..e1908a8483feb 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/handler.js
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/handler.js
@@ -21,15 +21,16 @@ import d3 from 'd3';
import _ from 'lodash';
import MarkdownIt from 'markdown-it';
+import { dispatchRenderComplete } from '../../../../kibana_utils/public';
+
+import { visTypes as chartTypes } from '../visualizations/vis_types';
import { NoResults } from '../errors';
import { Layout } from './layout/layout';
import { ChartTitle } from './chart_title';
import { Alerts } from './alerts';
import { Axis } from './axis/axis';
import { ChartGrid as Grid } from './chart_grid';
-import { visTypes as chartTypes } from '../visualizations/vis_types';
import { Binder } from './binder';
-import { dispatchRenderComplete } from '../../../../kibana_utils/public';
const markdownIt = new MarkdownIt({
html: false,
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json
index d52cb18727c05..50d6eab03e3f7 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json
@@ -31,7 +31,7 @@
},
"params": {
"date": true,
- "interval": "P1D",
+ "interval": 86400000,
"format": "YYYY-MM-DD",
"bounds": {
"min": "2019-05-10T04:00:00.000Z",
@@ -128,7 +128,7 @@
},
"xAxisLabel": "timestamp per day",
"ordered": {
- "interval": "P1D",
+ "interval": 86400000,
"date": true,
"min": 1557460800000,
"max": 1557656337342
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json
index 6e1a707229974..1987c59f6722b 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json
@@ -31,7 +31,7 @@
},
"params": {
"date": true,
- "interval": "P1D",
+ "interval": 86400000,
"format": "YYYY-MM-DD",
"bounds": {
"min": "2019-05-10T04:00:00.000Z",
@@ -128,7 +128,7 @@
},
"xAxisLabel": "timestamp per day",
"ordered": {
- "interval": "P1D",
+ "interval": 86400000,
"date": true,
"min": 1557460800000,
"max": 1557656337342
@@ -460,4 +460,4 @@
"50th percentile of AvgTicketPrice"
]
}
-}
\ No newline at end of file
+}
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json
index f7dd18f5eb712..ae1f3cbf24c33 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json
@@ -32,7 +32,7 @@
},
"params": {
"date": true,
- "interval": "P1D",
+ "interval": 86400000,
"format": "YYYY-MM-DD",
"bounds": {
"min": "2019-05-10T04:00:00.000Z",
@@ -453,4 +453,4 @@
}
],
"enableHover": true
-}
\ No newline at end of file
+}
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json
index 02062c987564e..f2ee245a8431f 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json
@@ -32,7 +32,7 @@
},
"params": {
"date": true,
- "interval": "P1D",
+ "interval": 86400000,
"format": "YYYY-MM-DD",
"bounds": {
"min": "2019-05-10T04:00:00.000Z",
@@ -455,4 +455,4 @@
}
],
"enableHover": true
-}
\ No newline at end of file
+}
diff --git a/src/plugins/vis_type_vislib/public/vislib/response_handler.js b/src/plugins/vis_type_vislib/public/vislib/response_handler.js
index 871ce97ad4480..9028b53fbd003 100644
--- a/src/plugins/vis_type_vislib/public/vislib/response_handler.js
+++ b/src/plugins/vis_type_vislib/public/vislib/response_handler.js
@@ -34,14 +34,16 @@ function tableResponseHandler(table, dimensions) {
table.rows.forEach((row, rowIndex) => {
const splitValue = row[splitColumn.id];
+ const formattedValue = splitColumnFormatter.convert(splitValue);
if (!splitMap.hasOwnProperty(splitValue)) {
splitMap[splitValue] = splitIndex++;
const tableGroup = {
$parent: converted,
- title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`,
+ title: `${formattedValue}: ${splitColumn.name}`,
name: splitColumn.name,
key: splitValue,
+ formattedKey: formattedValue,
column: splitColumnIndex,
row: rowIndex,
table,
diff --git a/src/plugins/vis_type_vislib/public/vislib/types.ts b/src/plugins/vis_type_vislib/public/vislib/types.ts
index ad59603663b84..5096015c99a90 100644
--- a/src/plugins/vis_type_vislib/public/vislib/types.ts
+++ b/src/plugins/vis_type_vislib/public/vislib/types.ts
@@ -33,6 +33,7 @@ export interface TableParent {
column: number;
row: number;
key: number;
+ formattedKey: string;
name: string;
}
export interface Table {
diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js
index a2b830ffaa781..40d15733b418d 100644
--- a/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js
+++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js
@@ -22,8 +22,8 @@ import { Chart } from './_chart';
import { gaugeTypes } from './gauges/gauge_types';
export class GaugeChart extends Chart {
- constructor(handler, chartEl, chartData, deps) {
- super(handler, chartEl, chartData, deps);
+ constructor(handler, chartEl, chartData, uiSettings) {
+ super(handler, chartEl, chartData, uiSettings);
this.gaugeConfig = handler.visConfig.get('gauge', {});
this.gauge = new gaugeTypes[this.gaugeConfig.type](this);
}
diff --git a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js
index 4564721464767..d725c29eef310 100644
--- a/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js
+++ b/src/plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js
@@ -40,8 +40,8 @@ const defaults = {
* @param chartData {Object} Elasticsearch query results for this specific chart
*/
export class HeatmapChart extends PointSeries {
- constructor(handler, chartEl, chartData, seriesConfigArgs, deps) {
- super(handler, chartEl, chartData, seriesConfigArgs, deps);
+ constructor(handler, chartEl, chartData, seriesConfigArgs, core) {
+ super(handler, chartEl, chartData, seriesConfigArgs, core);
this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults);
diff --git a/src/plugins/vis_type_vislib/server/ui_settings.ts b/src/plugins/vis_type_vislib/server/ui_settings.ts
index a48cbbae3d0ca..58564b4055daa 100644
--- a/src/plugins/vis_type_vislib/server/ui_settings.ts
+++ b/src/plugins/vis_type_vislib/server/ui_settings.ts
@@ -24,6 +24,8 @@ import { UiSettingsParams } from 'kibana/server';
import { DIMMING_OPACITY_SETTING, HEATMAP_MAX_BUCKETS_SETTING } from '../common';
export const uiSettings: Record = {
+ // TODO: move this to vis_type_xy when vislib is removed
+ // https://github.com/elastic/kibana/issues/56143
[DIMMING_OPACITY_SETTING]: {
name: i18n.translate('visTypeVislib.advancedSettings.visualization.dimmingOpacityTitle', {
defaultMessage: 'Dimming opacity',
diff --git a/src/plugins/vis_type_xy/README.md b/src/plugins/vis_type_xy/README.md
index 70ddb21c1e9db..549fc4e3ea189 100644
--- a/src/plugins/vis_type_xy/README.md
+++ b/src/plugins/vis_type_xy/README.md
@@ -1,2 +1,2 @@
Contains the new xy-axis chart using the elastic-charts library, which will eventually
-replace the vislib xy-axis (bar, area, line) charts.
\ No newline at end of file
+replace the vislib xy-axis charts including bar, area, and line.
diff --git a/src/plugins/vis_type_xy/common/index.ts b/src/plugins/vis_type_xy/common/index.ts
new file mode 100644
index 0000000000000..edee1ea3219db
--- /dev/null
+++ b/src/plugins/vis_type_xy/common/index.ts
@@ -0,0 +1,37 @@
+/*
+ * 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 { $Values } from '@kbn/utility-types';
+
+/**
+ * Type of charts able to render
+ */
+export const ChartType = Object.freeze({
+ Line: 'line' as const,
+ Area: 'area' as const,
+ Histogram: 'histogram' as const,
+});
+export type ChartType = $Values;
+
+/**
+ * Type of xy visualizations
+ */
+export type XyVisType = ChartType | 'horizontal_bar';
+
+export const LEGACY_CHARTS_LIBRARY = 'visualization:visualize:legacyChartsLibrary';
diff --git a/src/plugins/vis_type_xy/jest.config.js b/src/plugins/vis_type_xy/jest.config.js
new file mode 100644
index 0000000000000..556e518d4f4e1
--- /dev/null
+++ b/src/plugins/vis_type_xy/jest.config.js
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+module.exports = {
+ preset: '@kbn/test',
+ rootDir: '../../..',
+ roots: ['/src/plugins/vis_type_xy'],
+};
diff --git a/src/plugins/vis_type_xy/kibana.json b/src/plugins/vis_type_xy/kibana.json
index ca02da45e9112..14c3ce36bf375 100644
--- a/src/plugins/vis_type_xy/kibana.json
+++ b/src/plugins/vis_type_xy/kibana.json
@@ -3,5 +3,6 @@
"version": "kibana",
"server": true,
"ui": true,
- "requiredPlugins": ["charts", "expressions", "visualizations"]
+ "requiredPlugins": ["charts", "data", "expressions", "visualizations"],
+ "requiredBundles": ["kibanaUtils", "visDefaultEditor"]
}
diff --git a/src/plugins/vis_type_xy/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_type_xy/public/__snapshots__/to_ast.test.ts.snap
new file mode 100644
index 0000000000000..e6665c26a2815
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/__snapshots__/to_ast.test.ts.snap
@@ -0,0 +1,22 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`xy vis toExpressionAst function should match basic snapshot 1`] = `
+Object {
+ "addArgument": [Function],
+ "arguments": Object {
+ "type": Array [
+ "area",
+ ],
+ "visConfig": Array [
+ "{\\"type\\":\\"area\\",\\"grid\\":{\\"categoryLines\\":false,\\"style\\":{\\"color\\":\\"#eee\\"}},\\"categoryAxes\\":[{\\"id\\":\\"CategoryAxis-1\\",\\"type\\":\\"category\\",\\"position\\":\\"bottom\\",\\"show\\":true,\\"style\\":{},\\"scale\\":{\\"type\\":\\"linear\\"},\\"labels\\":{\\"show\\":true,\\"truncate\\":100},\\"title\\":{}}],\\"valueAxes\\":[{\\"id\\":\\"ValueAxis-1\\",\\"name\\":\\"LeftAxis-1\\",\\"type\\":\\"value\\",\\"position\\":\\"left\\",\\"show\\":true,\\"style\\":{},\\"scale\\":{\\"type\\":\\"linear\\",\\"mode\\":\\"normal\\"},\\"labels\\":{\\"show\\":true,\\"rotate\\":0,\\"filter\\":false,\\"truncate\\":100},\\"title\\":{\\"text\\":\\"Sum of total_quantity\\"}}],\\"seriesParams\\":[{\\"show\\":\\"true\\",\\"type\\":\\"area\\",\\"mode\\":\\"stacked\\",\\"data\\":{\\"label\\":\\"Sum of total_quantity\\",\\"id\\":\\"1\\"},\\"drawLinesBetweenPoints\\":true,\\"showCircles\\":true,\\"interpolate\\":\\"linear\\",\\"valueAxis\\":\\"ValueAxis-1\\"}],\\"addTooltip\\":true,\\"addLegend\\":true,\\"legendPosition\\":\\"top\\",\\"times\\":[],\\"addTimeMarker\\":false,\\"thresholdLine\\":{\\"show\\":false,\\"value\\":10,\\"width\\":1,\\"style\\":\\"full\\",\\"color\\":\\"#E7664C\\"},\\"labels\\":{},\\"dimensions\\":{\\"x\\":{\\"accessor\\":1,\\"format\\":{\\"id\\":\\"date\\",\\"params\\":{\\"pattern\\":\\"HH:mm:ss.SSS\\"}},\\"params\\":{}},\\"y\\":[{\\"accessor\\":0,\\"format\\":{\\"id\\":\\"number\\",\\"params\\":{\\"parsedUrl\\":{\\"origin\\":\\"http://localhost:5801\\",\\"pathname\\":\\"/app/visualize\\",\\"basePath\\":\\"\\"}}},\\"params\\":{}}],\\"series\\":[{\\"accessor\\":2,\\"format\\":{\\"id\\":\\"terms\\",\\"params\\":{\\"id\\":\\"string\\",\\"otherBucketLabel\\":\\"Other\\",\\"missingBucketLabel\\":\\"Missing\\",\\"parsedUrl\\":{\\"origin\\":\\"http://localhost:5801\\",\\"pathname\\":\\"/app/visualize\\",\\"basePath\\":\\"\\"}}},\\"params\\":{}}]}}",
+ ],
+ },
+ "getArgument": [Function],
+ "name": "xy_vis",
+ "removeArgument": [Function],
+ "replaceArgument": [Function],
+ "toAst": [Function],
+ "toString": [Function],
+ "type": "expression_function_builder",
+}
+`;
diff --git a/src/plugins/vis_type_xy/public/_chart.scss b/src/plugins/vis_type_xy/public/_chart.scss
new file mode 100644
index 0000000000000..ac9d4ed04aec4
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/_chart.scss
@@ -0,0 +1,7 @@
+.xyChart__container {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
diff --git a/src/plugins/vis_type_xy/public/components/_detailed_tooltip.scss b/src/plugins/vis_type_xy/public/components/_detailed_tooltip.scss
new file mode 100644
index 0000000000000..91b0a8d023290
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/components/_detailed_tooltip.scss
@@ -0,0 +1,34 @@
+.detailedTooltip {
+ @include euiToolTipStyle('s');
+ pointer-events: none;
+ max-width: $euiSizeXL * 10;
+ overflow: hidden;
+ padding: $euiSizeS;
+
+ table {
+ td,
+ th {
+ text-align: left;
+ padding: $euiSizeXS;
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ }
+ }
+}
+
+.detailedTooltip__header {
+ > :last-child {
+ margin-bottom: $euiSizeS;
+ }
+}
+
+.detailedTooltip__labelContainer,
+.detailedTooltip__valueContainer {
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+}
+
+.detailedTooltip__label {
+ font-weight: $euiFontWeightMedium;
+ color: shade($euiColorGhost, 20%);
+}
diff --git a/src/plugins/vis_type_xy/public/components/detailed_tooltip.tsx b/src/plugins/vis_type_xy/public/components/detailed_tooltip.tsx
new file mode 100644
index 0000000000000..3427baed41b8d
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/components/detailed_tooltip.tsx
@@ -0,0 +1,142 @@
+/*
+ * 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 React from 'react';
+import { isNil } from 'lodash';
+
+import {
+ CustomTooltip,
+ TooltipValue,
+ TooltipValueFormatter,
+ XYChartSeriesIdentifier,
+} from '@elastic/charts';
+
+import { BUCKET_TYPES } from '../../../data/public';
+
+import { Aspects } from '../types';
+
+import './_detailed_tooltip.scss';
+import { fillEmptyValue } from '../utils/get_series_name_fn';
+import { COMPLEX_SPLIT_ACCESSOR } from '../utils/accessors';
+
+interface TooltipData {
+ label: string;
+ value: string;
+}
+
+const getTooltipData = (
+ aspects: Aspects,
+ header: TooltipValue | null,
+ value: TooltipValue
+): TooltipData[] => {
+ const data: TooltipData[] = [];
+
+ if (header) {
+ const xFormatter =
+ aspects.x.aggType === BUCKET_TYPES.DATE_RANGE || aspects.x.aggType === BUCKET_TYPES.RANGE
+ ? null
+ : aspects.x.formatter;
+ data.push({
+ label: aspects.x.title,
+ value: xFormatter ? xFormatter(header.value) : `${header.value}`,
+ });
+ }
+
+ const valueSeries = value.seriesIdentifier as XYChartSeriesIdentifier;
+ const yAccessor = aspects.y.find(({ accessor }) => accessor === valueSeries.yAccessor) ?? null;
+
+ if (yAccessor) {
+ data.push({
+ label: yAccessor.title,
+ value: yAccessor.formatter ? yAccessor.formatter(value.value) : `${value.value}`,
+ });
+ }
+
+ if (aspects.z && !isNil(value.markValue)) {
+ data.push({
+ label: aspects.z.title,
+ value: aspects.z.formatter ? aspects.z.formatter(value.markValue) : `${value.markValue}`,
+ });
+ }
+
+ valueSeries.splitAccessors.forEach((splitValue, key) => {
+ const split = (aspects.series ?? []).find(({ accessor }, i) => {
+ return accessor === key || key === `${COMPLEX_SPLIT_ACCESSOR}::${i}`;
+ });
+
+ if (split) {
+ data.push({
+ label: split?.title,
+ value:
+ split?.formatter && !key.toString().startsWith(COMPLEX_SPLIT_ACCESSOR)
+ ? split?.formatter(splitValue)
+ : `${splitValue}`,
+ });
+ }
+ });
+
+ return data;
+};
+
+const renderData = ({ label, value: rawValue }: TooltipData, index: number) => {
+ const value = fillEmptyValue(rawValue);
+ return label && value ? (
+
+
+ {label}
+ |
+
+
+ {value}
+ |
+
+ ) : null;
+};
+
+export const getDetailedTooltip = (aspects: Aspects) => (
+ headerFormatter?: TooltipValueFormatter
+): CustomTooltip => {
+ return function DetailedTooltip({ header, values }) {
+ // Note: first value is not necessarily the closest value
+ // To be fixed with https://github.com/elastic/elastic-charts/issues/835
+ // TODO: Allow multiple values to be displayed in tooltip
+ const highlightedValue = values.find(({ isHighlighted }) => isHighlighted);
+
+ if (!highlightedValue) {
+ return null;
+ }
+
+ const tooltipData = getTooltipData(aspects, header, highlightedValue);
+
+ if (tooltipData.length === 0) {
+ return null;
+ }
+
+ return (
+
+ {headerFormatter && header && (
+
{headerFormatter(header)}
+ )}
+
+ {tooltipData.map(renderData)}
+
+
+ );
+ };
+};
diff --git a/src/plugins/vis_type_xy/public/components/index.ts b/src/plugins/vis_type_xy/public/components/index.ts
new file mode 100644
index 0000000000000..d8d55c77b7a8a
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/components/index.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 { XYAxis } from './xy_axis';
+export { XYEndzones } from './xy_endzones';
+export { XYCurrentTime } from './xy_current_time';
+export { XYSettings } from './xy_settings';
+export { XYThresholdLine } from './xy_threshold_line';
+export { SplitChartWarning } from './split_chart_warning';
diff --git a/src/plugins/vis_type_xy/public/components/split_chart_warning.tsx b/src/plugins/vis_type_xy/public/components/split_chart_warning.tsx
new file mode 100644
index 0000000000000..7265e70a791a3
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/components/split_chart_warning.tsx
@@ -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 React, { FC } from 'react';
+
+import { EuiLink, EuiCallOut } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import { getDocLinks } from '../services';
+
+export const SplitChartWarning: FC = () => {
+ const advancedSettingsLink = getDocLinks().links.management.visualizationSettings;
+
+ return (
+
+
+
+
+ ),
+ }}
+ />
+
+ );
+};
diff --git a/src/plugins/inspector/common/adapters/data/types.ts b/src/plugins/vis_type_xy/public/components/xy_axis.tsx
similarity index 53%
rename from src/plugins/inspector/common/adapters/data/types.ts
rename to src/plugins/vis_type_xy/public/components/xy_axis.tsx
index 040724f4ae36e..b64f2bf1ec0ec 100644
--- a/src/plugins/inspector/common/adapters/data/types.ts
+++ b/src/plugins/vis_type_xy/public/components/xy_axis.tsx
@@ -17,32 +17,39 @@
* under the License.
*/
-export interface TabularDataValue {
- formatted: string;
- raw: unknown;
-}
+import React, { FC } from 'react';
-export interface TabularDataColumn {
- name: string;
- field: string;
- filter?: (value: TabularDataValue) => void;
- filterOut?: (value: TabularDataValue) => void;
-}
+import { Axis } from '@elastic/charts';
-export type TabularDataRow = Record;
+import { AxisConfig } from '../types';
-export interface TabularData {
- columns: TabularDataColumn[];
- rows: TabularDataRow[];
-}
+type XYAxisPros = AxisConfig;
-export type TabularCallback = () => TabularData | Promise;
-
-export interface TabularHolder {
- data: TabularData | null;
- options: TabularLoaderOptions;
-}
-
-export interface TabularLoaderOptions {
- returnsFormattedValues?: boolean;
-}
+export const XYAxis: FC = ({
+ id,
+ title,
+ show,
+ position,
+ groupId,
+ grid,
+ ticks,
+ domain,
+ style,
+ integersOnly,
+}) => (
+
+);
diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/__mocks__/@elastic/charts.js b/src/plugins/vis_type_xy/public/components/xy_current_time.tsx
similarity index 61%
rename from src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/__mocks__/@elastic/charts.js
rename to src/plugins/vis_type_xy/public/components/xy_current_time.tsx
index 19bfe685cac90..66ad4fda3bec7 100644
--- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/__mocks__/@elastic/charts.js
+++ b/src/plugins/vis_type_xy/public/components/xy_current_time.tsx
@@ -17,28 +17,21 @@
* under the License.
*/
-export const CurveType = {
- CURVE_CARDINAL: 0,
- CURVE_NATURAL: 1,
- CURVE_MONOTONE_X: 2,
- CURVE_MONOTONE_Y: 3,
- CURVE_BASIS: 4,
- CURVE_CATMULL_ROM: 5,
- CURVE_STEP: 6,
- CURVE_STEP_AFTER: 7,
- CURVE_STEP_BEFORE: 8,
- LINEAR: 9,
-};
+import React, { FC } from 'react';
+import { DomainRange } from '@elastic/charts';
+import { CurrentTime } from '../../../charts/public';
-export const ScaleType = {
- Linear: 'linear',
- Ordinal: 'ordinal',
- Log: 'log',
- Sqrt: 'sqrt',
- Time: 'time',
-};
+interface XYCurrentTime {
+ enabled: boolean;
+ isDarkMode: boolean;
+ domain?: DomainRange;
+}
-export const BarSeries = () => null;
-export const AreaSeries = () => null;
+export const XYCurrentTime: FC = ({ enabled, isDarkMode, domain }) => {
+ if (!enabled) {
+ return null;
+ }
-export { LIGHT_THEME, DARK_THEME } from '@elastic/charts';
+ const domainEnd = domain && 'max' in domain ? domain.max : undefined;
+ return ;
+};
diff --git a/src/plugins/vis_type_xy/public/components/xy_endzones.tsx b/src/plugins/vis_type_xy/public/components/xy_endzones.tsx
new file mode 100644
index 0000000000000..33e1d1e18bb1d
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/components/xy_endzones.tsx
@@ -0,0 +1,68 @@
+/*
+ * 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 React, { FC } from 'react';
+
+import { DomainRange } from '@elastic/charts';
+
+import { Endzones } from '../../../charts/public';
+
+interface XYEndzones {
+ enabled: boolean;
+ isDarkMode: boolean;
+ isFullBin: boolean;
+ hideTooltips?: boolean;
+ domain?: DomainRange;
+ adjustedDomain?: DomainRange;
+}
+
+export const XYEndzones: FC = ({
+ enabled,
+ isDarkMode,
+ isFullBin,
+ hideTooltips,
+ domain,
+ adjustedDomain,
+}) => {
+ if (
+ enabled &&
+ domain &&
+ adjustedDomain &&
+ 'min' in domain &&
+ 'max' in domain &&
+ domain.minInterval !== undefined &&
+ 'min' in adjustedDomain &&
+ 'max' in adjustedDomain
+ ) {
+ return (
+
+ );
+ }
+
+ return null;
+};
diff --git a/src/plugins/vis_type_xy/public/components/xy_settings.tsx b/src/plugins/vis_type_xy/public/components/xy_settings.tsx
new file mode 100644
index 0000000000000..3682fdf3350b0
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/components/xy_settings.tsx
@@ -0,0 +1,182 @@
+/*
+ * 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 React, { FC } from 'react';
+
+import {
+ Direction,
+ Settings,
+ DomainRange,
+ Position,
+ PartialTheme,
+ ElementClickListener,
+ BrushEndListener,
+ RenderChangeListener,
+ LegendAction,
+ LegendColorPicker,
+ TooltipProps,
+ TickFormatter,
+} from '@elastic/charts';
+
+import { renderEndzoneTooltip } from '../../../charts/public';
+
+import { getThemeService, getUISettings } from '../services';
+import { VisConfig } from '../types';
+import { fillEmptyValue } from '../utils/get_series_name_fn';
+
+declare global {
+ interface Window {
+ /**
+ * Flag used to enable debugState on elastic charts
+ */
+ _echDebugStateFlag?: boolean;
+ }
+}
+
+type XYSettingsProps = Pick<
+ VisConfig,
+ | 'markSizeRatio'
+ | 'rotation'
+ | 'enableHistogramMode'
+ | 'tooltip'
+ | 'isTimeChart'
+ | 'xAxis'
+ | 'orderBucketsBySum'
+> & {
+ xDomain?: DomainRange;
+ adjustedXDomain?: DomainRange;
+ showLegend: boolean;
+ onElementClick: ElementClickListener;
+ onBrushEnd?: BrushEndListener;
+ onRenderChange: RenderChangeListener;
+ legendAction?: LegendAction;
+ legendColorPicker: LegendColorPicker;
+ legendPosition: Position;
+};
+
+export const XYSettings: FC = ({
+ markSizeRatio,
+ rotation,
+ enableHistogramMode,
+ tooltip,
+ isTimeChart,
+ xAxis,
+ orderBucketsBySum,
+ xDomain,
+ adjustedXDomain,
+ showLegend,
+ onElementClick,
+ onBrushEnd,
+ onRenderChange,
+ legendAction,
+ legendColorPicker,
+ legendPosition,
+}) => {
+ const themeService = getThemeService();
+ const theme = themeService.useChartsTheme();
+ const baseTheme = themeService.useChartsBaseTheme();
+ const dimmingOpacity = getUISettings().get('visualization:dimmingOpacity');
+ const fontSize =
+ typeof theme.barSeriesStyle?.displayValue?.fontSize === 'number'
+ ? { min: theme.barSeriesStyle?.displayValue?.fontSize }
+ : theme.barSeriesStyle?.displayValue?.fontSize ?? { min: 8 };
+
+ const themeOverrides: PartialTheme = {
+ markSizeRatio,
+ sharedStyle: {
+ unhighlighted: {
+ opacity: dimmingOpacity,
+ },
+ },
+ barSeriesStyle: {
+ displayValue: {
+ fontSize,
+ alignment: {
+ horizontal: 'center',
+ vertical: 'middle',
+ },
+ },
+ },
+ axes: {
+ axisTitle: {
+ padding: {
+ outer: 10,
+ },
+ },
+ },
+ chartMargins:
+ legendPosition === Position.Top || legendPosition === Position.Right
+ ? {
+ bottom: (theme.chartMargins?.bottom ?? 0) + 10,
+ }
+ : {
+ right: (theme.chartMargins?.right ?? 0) + 10,
+ },
+ };
+
+ const headerValueFormatter: TickFormatter | undefined = xAxis.ticks?.formatter
+ ? (value) => fillEmptyValue(xAxis.ticks?.formatter?.(value)) ?? ''
+ : undefined;
+ const headerFormatter =
+ isTimeChart && xDomain && adjustedXDomain
+ ? renderEndzoneTooltip(
+ xDomain.minInterval,
+ 'min' in xDomain ? xDomain.min : undefined,
+ 'max' in xDomain ? xDomain.max : undefined,
+ headerValueFormatter,
+ !tooltip.detailedTooltip
+ )
+ : headerValueFormatter &&
+ (tooltip.detailedTooltip ? undefined : ({ value }: any) => headerValueFormatter(value));
+
+ const tooltipProps: TooltipProps = tooltip.detailedTooltip
+ ? {
+ ...tooltip,
+ customTooltip: tooltip.detailedTooltip(headerFormatter),
+ headerFormatter: undefined,
+ }
+ : { ...tooltip, headerFormatter };
+
+ return (
+
+ );
+};
diff --git a/src/plugins/vis_type_xy/public/components/xy_threshold_line.tsx b/src/plugins/vis_type_xy/public/components/xy_threshold_line.tsx
new file mode 100644
index 0000000000000..46b0a009807a2
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/components/xy_threshold_line.tsx
@@ -0,0 +1,58 @@
+/*
+ * 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 React, { FC } from 'react';
+
+import { AnnotationDomainTypes, LineAnnotation } from '@elastic/charts';
+
+import { ThresholdLineConfig } from '../types';
+
+type XYThresholdLineProps = ThresholdLineConfig & {
+ groupId?: string;
+};
+
+export const XYThresholdLine: FC = ({
+ show,
+ value: dataValue,
+ color,
+ width,
+ groupId,
+ dash,
+}) => {
+ if (!show) {
+ return null;
+ }
+
+ return (
+
+ );
+};
diff --git a/src/plugins/vis_type_xy/public/config/get_agg_id.ts b/src/plugins/vis_type_xy/public/config/get_agg_id.ts
new file mode 100644
index 0000000000000..7923145d83013
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/config/get_agg_id.ts
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+/**
+ * Get agg id from accessor
+ *
+ * For now this is determined by the esaggs column name. Could be cleaned up in the future.
+ */
+export const getAggId = (accessor: string) => (accessor ?? '').split('-').pop() ?? '';
diff --git a/src/plugins/vis_type_xy/public/config/get_aspects.ts b/src/plugins/vis_type_xy/public/config/get_aspects.ts
new file mode 100644
index 0000000000000..73096de0a5d51
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/config/get_aspects.ts
@@ -0,0 +1,95 @@
+/*
+ * 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 { compact } from 'lodash';
+
+import { i18n } from '@kbn/i18n';
+
+import { DatatableColumn } from '../../../expressions/public';
+
+import { Aspect, Dimension, Aspects, Dimensions } from '../types';
+import { getFormatService } from '../services';
+import { getAggId } from './get_agg_id';
+
+export function getEmptyAspect(): Aspect {
+ return {
+ accessor: null,
+ aggId: null,
+ aggType: null,
+ title: i18n.translate('visTypeXy.aggResponse.allDocsTitle', {
+ defaultMessage: 'All docs',
+ }),
+ params: {
+ defaultValue: '_all',
+ },
+ };
+}
+export function getAspects(columns: DatatableColumn[], { x, y, z, series }: Dimensions): Aspects {
+ const seriesDimensions = Array.isArray(series) || series === undefined ? series : [series];
+
+ return {
+ x: getAspectsFromDimension(columns, x) ?? getEmptyAspect(),
+ y: getAspectsFromDimension(columns, y) ?? [],
+ z: z && z?.length > 0 ? getAspectsFromDimension(columns, z[0]) : undefined,
+ series: getAspectsFromDimension(columns, seriesDimensions),
+ };
+}
+
+function getAspectsFromDimension(
+ columns: DatatableColumn[],
+ dimension?: Dimension | null
+): Aspect | undefined;
+function getAspectsFromDimension(
+ columns: DatatableColumn[],
+ dimensions?: Dimension[] | null
+): Aspect[] | undefined;
+function getAspectsFromDimension(
+ columns: DatatableColumn[],
+ dimensions?: Dimension | Dimension[] | null
+): Aspect[] | Aspect | undefined {
+ if (!dimensions) {
+ return;
+ }
+
+ if (Array.isArray(dimensions)) {
+ return compact(
+ dimensions.map((d) => {
+ const column = d && columns[d.accessor];
+ return column && getAspect(column, d);
+ })
+ );
+ }
+
+ const column = columns[dimensions.accessor];
+ return column && getAspect(column, dimensions);
+}
+
+const getAspect = (
+ { id: accessor, name: title }: DatatableColumn,
+ { accessor: column, format, params, aggType }: Dimension
+): Aspect => ({
+ accessor,
+ column,
+ title,
+ format,
+ aggType,
+ aggId: getAggId(accessor),
+ formatter: (value: any) => getFormatService().deserialize(format).convert(value),
+ params,
+});
diff --git a/src/plugins/vis_type_xy/public/config/get_axis.ts b/src/plugins/vis_type_xy/public/config/get_axis.ts
new file mode 100644
index 0000000000000..43a9e25e0e287
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/config/get_axis.ts
@@ -0,0 +1,198 @@
+/*
+ * 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, isNil } from 'lodash';
+
+import { AxisSpec, TickFormatter, YDomainRange, ScaleType as ECScaleType } from '@elastic/charts';
+
+import { LabelRotation } from '../../../charts/public';
+import { BUCKET_TYPES } from '../../../data/public';
+
+import {
+ Aspect,
+ CategoryAxis,
+ Grid,
+ AxisConfig,
+ TickOptions,
+ ScaleConfig,
+ Scale,
+ ScaleType,
+ AxisType,
+ XScaleType,
+ YScaleType,
+ SeriesParam,
+} from '../types';
+import { fillEmptyValue } from '../utils/get_series_name_fn';
+
+export function getAxis(
+ { type, title: axisTitle, labels, scale: axisScale, ...axis }: CategoryAxis,
+ { categoryLines, valueAxis }: Grid,
+ { params, format, formatter, title: fallbackTitle = '', aggType }: Aspect,
+ seriesParams: SeriesParam[],
+ isDateHistogram = false
+): AxisConfig {
+ const isCategoryAxis = type === AxisType.Category;
+ // Hide unassigned axis, not supported in elastic charts
+ // TODO: refactor when disallowing unassigned axes
+ // https://github.com/elastic/kibana/issues/82752
+ const show =
+ (isCategoryAxis || seriesParams.some(({ valueAxis: id }) => id === axis.id)) && axis.show;
+ const groupId = axis.id;
+
+ const grid = isCategoryAxis
+ ? {
+ show: categoryLines,
+ }
+ : {
+ show: valueAxis === axis.id,
+ };
+ // Date range formatter applied on xAccessor
+ const tickFormatter =
+ aggType === BUCKET_TYPES.DATE_RANGE || aggType === BUCKET_TYPES.RANGE ? identity : formatter;
+ const ticks: TickOptions = {
+ formatter: tickFormatter,
+ labelFormatter: getLabelFormatter(labels.truncate, tickFormatter),
+ show: labels.show,
+ rotation: labels.rotate,
+ showOverlappingLabels: !labels.filter,
+ showDuplicates: !labels.filter,
+ };
+ const scale = getScale(axisScale, params, format, isCategoryAxis);
+ const title = axisTitle.text || fallbackTitle;
+ const fallbackRotation =
+ isCategoryAxis && isDateHistogram ? LabelRotation.Horizontal : LabelRotation.Vertical;
+
+ return {
+ ...axis,
+ show,
+ groupId,
+ title,
+ ticks,
+ grid,
+ scale,
+ style: getAxisStyle(ticks, title, fallbackRotation),
+ domain: getAxisDomain(scale, isCategoryAxis),
+ integersOnly: aggType === 'count',
+ };
+}
+
+function getLabelFormatter(
+ truncate?: number | null,
+ formatter?: TickFormatter
+): TickFormatter | undefined {
+ if (truncate === null || truncate === undefined) {
+ return formatter;
+ }
+
+ return (value: any) => {
+ const formattedStringValue = `${formatter ? formatter(value) : value}`;
+ const finalValue = fillEmptyValue(formattedStringValue);
+
+ if (finalValue.length > truncate) {
+ return `${finalValue.slice(0, truncate)}...`;
+ }
+
+ return finalValue;
+ };
+}
+
+function getScaleType(
+ scale?: Scale,
+ isNumber?: boolean,
+ isTime = false,
+ isHistogram = false
+): ECScaleType | undefined {
+ if (isTime) return ECScaleType.Time;
+ if (isHistogram) return ECScaleType.Linear;
+
+ if (!isNumber) {
+ return ECScaleType.Ordinal;
+ }
+
+ const type = scale?.type;
+ if (type === ScaleType.SquareRoot) {
+ return ECScaleType.Sqrt;
+ }
+
+ return type;
+}
+
+function getScale(
+ scale: Scale,
+ params: Aspect['params'],
+ format: Aspect['format'],
+ isCategoryAxis: boolean
+): ScaleConfig {
+ const type = (isCategoryAxis
+ ? getScaleType(
+ scale,
+ format?.id === 'number' || (format?.params?.id === 'number' && format?.id !== 'range'),
+ 'date' in params,
+ 'interval' in params
+ )
+ : getScaleType(scale, true)) as S;
+
+ return {
+ ...scale,
+ type,
+ };
+}
+
+function getAxisStyle(
+ ticks?: TickOptions,
+ title?: string,
+ rotationFallback: LabelRotation = LabelRotation.Vertical
+): AxisSpec['style'] {
+ return {
+ axisTitle: {
+ visible: (title ?? '').trim().length > 0,
+ },
+ tickLabel: {
+ visible: ticks?.show,
+ rotation: -(ticks?.rotation ?? rotationFallback),
+ },
+ };
+}
+
+function getAxisDomain(
+ scale: ScaleConfig,
+ isCategoryAxis: boolean
+): YDomainRange | undefined {
+ if (isCategoryAxis || !scale) {
+ return;
+ }
+
+ const { min, max, defaultYExtents, boundsMargin } = scale;
+ const fit = defaultYExtents;
+ const padding = boundsMargin;
+
+ if (!isNil(min) && !isNil(max)) {
+ return { fit, padding, min, max };
+ }
+
+ if (!isNil(min)) {
+ return { fit, padding, min };
+ }
+
+ if (!isNil(max)) {
+ return { fit, padding, max };
+ }
+
+ return { fit, padding };
+}
diff --git a/src/plugins/vis_type_xy/public/config/get_config.ts b/src/plugins/vis_type_xy/public/config/get_config.ts
new file mode 100644
index 0000000000000..f0c5740b1307b
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/config/get_config.ts
@@ -0,0 +1,134 @@
+/*
+ * 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 { ScaleContinuousType } from '@elastic/charts/dist/scales';
+
+import { Datatable } from '../../../expressions/public';
+import { BUCKET_TYPES } from '../../../data/public';
+
+import {
+ Aspect,
+ AxisConfig,
+ DateHistogramParams,
+ SeriesParam,
+ VisConfig,
+ VisParams,
+ XScaleType,
+ YScaleType,
+} from '../types';
+import { getThresholdLine } from './get_threshold_line';
+import { getRotation } from './get_rotation';
+import { getTooltip } from './get_tooltip';
+import { getLegend } from './get_legend';
+import { getAxis } from './get_axis';
+import { getAspects } from './get_aspects';
+import { ChartType } from '../index';
+
+export function getConfig(table: Datatable, params: VisParams): VisConfig {
+ const {
+ thresholdLine,
+ orderBucketsBySum,
+ addTimeMarker,
+ radiusRatio,
+ labels,
+ fittingFunction,
+ detailedTooltip,
+ isVislibVis,
+ } = params;
+ const aspects = getAspects(table.columns, params.dimensions);
+ const xAxis = getAxis(
+ params.categoryAxes[0],
+ params.grid,
+ aspects.x,
+ params.seriesParams,
+ params.dimensions.x?.aggType === BUCKET_TYPES.DATE_HISTOGRAM
+ );
+ const tooltip = getTooltip(aspects, params);
+ const yAxes = params.valueAxes.map((a) =>
+ // uses first y aspect in array for formatting axis
+ getAxis(a, params.grid, aspects.y[0], params.seriesParams)
+ );
+ const enableHistogramMode =
+ (params.dimensions.x?.aggType === BUCKET_TYPES.DATE_HISTOGRAM ||
+ params.dimensions.x?.aggType === BUCKET_TYPES.HISTOGRAM) &&
+ shouldEnableHistogramMode(params.seriesParams, aspects.y, yAxes);
+ const isTimeChart = (aspects.x.params as DateHistogramParams).date ?? false;
+
+ return {
+ // NOTE: downscale ratio to match current vislib implementation
+ markSizeRatio: radiusRatio * 0.6,
+ fittingFunction,
+ detailedTooltip,
+ orderBucketsBySum,
+ isTimeChart,
+ isVislibVis,
+ showCurrentTime: addTimeMarker && isTimeChart,
+ showValueLabel: labels.show ?? false,
+ enableHistogramMode,
+ tooltip,
+ aspects,
+ xAxis,
+ yAxes,
+ legend: getLegend(params),
+ rotation: getRotation(params.categoryAxes[0]),
+ thresholdLine: getThresholdLine(thresholdLine, yAxes, params.seriesParams),
+ };
+}
+
+/**
+ * disables histogram mode for any config that has non-stacked clustered bars
+ *
+ * @param seriesParams
+ * @param yAspects
+ * @param yAxes
+ */
+const shouldEnableHistogramMode = (
+ seriesParams: SeriesParam[],
+ yAspects: Aspect[],
+ yAxes: Array>
+): boolean => {
+ const bars = seriesParams.filter(({ type, data: { id: paramId } }) => {
+ return (
+ type === ChartType.Histogram && yAspects.find(({ aggId }) => aggId === paramId) !== undefined
+ );
+ });
+
+ if (bars.length === 1) {
+ return true;
+ }
+
+ const groupIds = [
+ ...bars.reduce>((acc, { valueAxis: groupId, mode }) => {
+ acc.add(groupId);
+ return acc;
+ }, new Set()),
+ ];
+
+ if (groupIds.length > 1) {
+ return false;
+ }
+
+ const test = bars.every(({ valueAxis: groupId, mode }) => {
+ const yAxisScale = yAxes.find(({ groupId: axisGroupId }) => axisGroupId === groupId)?.scale;
+
+ return mode === 'stacked' || yAxisScale?.mode === 'percentage';
+ });
+
+ return test;
+};
diff --git a/src/plugins/vis_type_xy/public/config/get_legend.ts b/src/plugins/vis_type_xy/public/config/get_legend.ts
new file mode 100644
index 0000000000000..a376ec3c4fb96
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/config/get_legend.ts
@@ -0,0 +1,27 @@
+/*
+ * 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 { LegendOptions, VisParams } from '../types';
+
+export function getLegend({ addLegend, legendPosition }: VisParams): LegendOptions {
+ return {
+ show: addLegend,
+ position: legendPosition,
+ };
+}
diff --git a/src/plugins/vis_type_xy/public/config/get_rotation.ts b/src/plugins/vis_type_xy/public/config/get_rotation.ts
new file mode 100644
index 0000000000000..3c1e9a8f9130a
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/config/get_rotation.ts
@@ -0,0 +1,30 @@
+/*
+ * 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 { Rotation } from '@elastic/charts';
+
+import { CategoryAxis } from '../types';
+
+export function getRotation({ position }: CategoryAxis): Rotation {
+ if (position === 'left' || position === 'right') {
+ return 90;
+ }
+
+ return 0;
+}
diff --git a/src/plugins/inspector/common/adapters/data/data_adapter.ts b/src/plugins/vis_type_xy/public/config/get_threshold_line.ts
similarity index 51%
rename from src/plugins/inspector/common/adapters/data/data_adapter.ts
rename to src/plugins/vis_type_xy/public/config/get_threshold_line.ts
index a21aa7db39145..861769f829074 100644
--- a/src/plugins/inspector/common/adapters/data/data_adapter.ts
+++ b/src/plugins/vis_type_xy/public/config/get_threshold_line.ts
@@ -17,24 +17,38 @@
* under the License.
*/
-import { EventEmitter } from 'events';
-import { TabularCallback, TabularHolder, TabularLoaderOptions } from './types';
+import {
+ ThresholdLineConfig,
+ ThresholdLine,
+ ThresholdLineStyle,
+ AxisConfig,
+ SeriesParam,
+ YScaleType,
+} from '../types';
-export class DataAdapter extends EventEmitter {
- private tabular?: TabularCallback;
- private tabularOptions?: TabularLoaderOptions;
+export function getThresholdLine(
+ { style, ...rest }: ThresholdLine,
+ yAxes: Array>,
+ seriesParams: SeriesParam[]
+): ThresholdLineConfig {
+ const groupId = yAxes.find(({ id }) => seriesParams.some(({ valueAxis }) => id === valueAxis))
+ ?.groupId;
- public setTabularLoader(callback: TabularCallback, options: TabularLoaderOptions = {}): void {
- this.tabular = callback;
- this.tabularOptions = options;
- this.emit('change', 'tabular');
- }
+ return {
+ ...rest,
+ dash: getDash(style),
+ groupId,
+ };
+}
- public getTabular(): Promise {
- if (!this.tabular || !this.tabularOptions) {
- return Promise.resolve({ data: null, options: {} });
- }
- const options = this.tabularOptions;
- return Promise.resolve(this.tabular()).then((data) => ({ data, options }));
+function getDash(style: ThresholdLineStyle): number[] | undefined {
+ switch (style) {
+ case ThresholdLineStyle.Dashed:
+ return [10, 5];
+ case ThresholdLineStyle.DotDashed:
+ return [20, 5, 5, 5];
+ case ThresholdLineStyle.Full:
+ default:
+ return;
}
}
diff --git a/src/plugins/vis_type_xy/public/config/get_tooltip.ts b/src/plugins/vis_type_xy/public/config/get_tooltip.ts
new file mode 100644
index 0000000000000..87146eeca9155
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/config/get_tooltip.ts
@@ -0,0 +1,33 @@
+/*
+ * 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 { TooltipType } from '@elastic/charts';
+
+import { Aspects, VisParams, TooltipConfig } from '../types';
+import { getDetailedTooltip } from '../components/detailed_tooltip';
+
+export function getTooltip(
+ aspects: Aspects,
+ { addTooltip, detailedTooltip }: VisParams
+): TooltipConfig {
+ return {
+ type: addTooltip ? TooltipType.VerticalCursor : TooltipType.None,
+ detailedTooltip: detailedTooltip ? getDetailedTooltip(aspects) : undefined,
+ };
+}
diff --git a/src/plugins/vis_type_xy/public/config/index.ts b/src/plugins/vis_type_xy/public/config/index.ts
new file mode 100644
index 0000000000000..2b0e32f726a6c
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/config/index.ts
@@ -0,0 +1,21 @@
+/*
+ * 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 { getConfig } from './get_config';
+export { getAggId } from './get_agg_id';
diff --git a/src/plugins/vis_type_xy/public/editor/collections.ts b/src/plugins/vis_type_xy/public/editor/collections.ts
new file mode 100644
index 0000000000000..0149bc476f5c5
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/editor/collections.ts
@@ -0,0 +1,201 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+import { Fit } from '@elastic/charts';
+
+import { AxisMode, ChartMode, InterpolationMode, ThresholdLineStyle } from '../types';
+import { ChartType } from '../../common';
+import { LabelRotation } from '../../../charts/public';
+import { getScaleTypes } from './scale_types';
+import { getPositions } from './positions';
+
+export { getScaleTypes, getPositions };
+
+export const getChartTypes = () => [
+ {
+ text: i18n.translate('visTypeXy.chartTypes.lineText', {
+ defaultMessage: 'Line',
+ }),
+ value: ChartType.Line,
+ },
+ {
+ text: i18n.translate('visTypeXy.chartTypes.areaText', {
+ defaultMessage: 'Area',
+ }),
+ value: ChartType.Area,
+ },
+ {
+ text: i18n.translate('visTypeXy.chartTypes.barText', {
+ defaultMessage: 'Bar',
+ }),
+ value: ChartType.Histogram,
+ },
+];
+
+export const getChartModes = () => [
+ {
+ text: i18n.translate('visTypeXy.chartModes.normalText', {
+ defaultMessage: 'Normal',
+ }),
+ value: ChartMode.Normal,
+ },
+ {
+ text: i18n.translate('visTypeXy.chartModes.stackedText', {
+ defaultMessage: 'Stacked',
+ }),
+ value: ChartMode.Stacked,
+ },
+];
+
+export const getInterpolationModes = () => [
+ {
+ text: i18n.translate('visTypeXy.interpolationModes.straightText', {
+ defaultMessage: 'Straight',
+ }),
+ value: InterpolationMode.Linear,
+ },
+ {
+ text: i18n.translate('visTypeXy.interpolationModes.smoothedText', {
+ defaultMessage: 'Smoothed',
+ }),
+ value: InterpolationMode.Cardinal,
+ },
+ {
+ text: i18n.translate('visTypeXy.interpolationModes.steppedText', {
+ defaultMessage: 'Stepped',
+ }),
+ value: InterpolationMode.StepAfter,
+ },
+];
+
+export const getAxisModes = () => [
+ {
+ text: i18n.translate('visTypeXy.axisModes.normalText', {
+ defaultMessage: 'Normal',
+ }),
+ value: AxisMode.Normal,
+ },
+ {
+ text: i18n.translate('visTypeXy.axisModes.percentageText', {
+ defaultMessage: 'Percentage',
+ }),
+ value: AxisMode.Percentage,
+ },
+ {
+ text: i18n.translate('visTypeXy.axisModes.wiggleText', {
+ defaultMessage: 'Wiggle',
+ }),
+ value: AxisMode.Wiggle,
+ },
+ {
+ text: i18n.translate('visTypeXy.axisModes.silhouetteText', {
+ defaultMessage: 'Silhouette',
+ }),
+ value: AxisMode.Silhouette,
+ },
+];
+
+export const getThresholdLineStyles = () => [
+ {
+ value: ThresholdLineStyle.Full,
+ text: i18n.translate('visTypeXy.thresholdLine.style.fullText', {
+ defaultMessage: 'Full',
+ }),
+ },
+ {
+ value: ThresholdLineStyle.Dashed,
+ text: i18n.translate('visTypeXy.thresholdLine.style.dashedText', {
+ defaultMessage: 'Dashed',
+ }),
+ },
+ {
+ value: ThresholdLineStyle.DotDashed,
+ text: i18n.translate('visTypeXy.thresholdLine.style.dotdashedText', {
+ defaultMessage: 'Dot-dashed',
+ }),
+ },
+];
+
+export const getRotateOptions = () => [
+ {
+ text: i18n.translate('visTypeXy.categoryAxis.rotate.horizontalText', {
+ defaultMessage: 'Horizontal',
+ }),
+ value: LabelRotation.Horizontal,
+ },
+ {
+ text: i18n.translate('visTypeXy.categoryAxis.rotate.verticalText', {
+ defaultMessage: 'Vertical',
+ }),
+ value: LabelRotation.Vertical,
+ },
+ {
+ text: i18n.translate('visTypeXy.categoryAxis.rotate.angledText', {
+ defaultMessage: 'Angled',
+ }),
+ value: LabelRotation.Angled,
+ },
+];
+
+export const getFittingFunctions = () =>
+ [
+ {
+ value: Fit.None,
+ text: i18n.translate('visTypeXy.fittingFunctionsTitle.none', {
+ defaultMessage: 'Hide (Do not fill gaps)',
+ }),
+ },
+ {
+ value: Fit.Zero,
+ text: i18n.translate('visTypeXy.fittingFunctionsTitle.zero', {
+ defaultMessage: 'Zero (Fill gaps with zeros)',
+ }),
+ },
+ {
+ value: Fit.Linear,
+ text: i18n.translate('visTypeXy.fittingFunctionsTitle.linear', {
+ defaultMessage: 'Linear (Fill gaps with a line)',
+ }),
+ },
+ {
+ value: Fit.Carry,
+ text: i18n.translate('visTypeXy.fittingFunctionsTitle.carry', {
+ defaultMessage: 'Last (Fill gaps with the last value)',
+ }),
+ },
+ {
+ value: Fit.Lookahead,
+ text: i18n.translate('visTypeXy.fittingFunctionsTitle.lookahead', {
+ defaultMessage: 'Next (Fill gaps with the next value)',
+ }),
+ },
+ ] as const;
+
+export const getConfigCollections = () => ({
+ legendPositions: getPositions(),
+ positions: getPositions(),
+ chartTypes: getChartTypes(),
+ axisModes: getAxisModes(),
+ scaleTypes: getScaleTypes(),
+ chartModes: getChartModes(),
+ interpolationModes: getInterpolationModes(),
+ thresholdLineStyles: getThresholdLineStyles(),
+ fittingFunctions: getFittingFunctions(),
+});
diff --git a/src/plugins/vis_type_vislib/public/utils/common_config.tsx b/src/plugins/vis_type_xy/public/editor/common_config.tsx
similarity index 59%
rename from src/plugins/vis_type_vislib/public/utils/common_config.tsx
rename to src/plugins/vis_type_xy/public/editor/common_config.tsx
index de867dc72bba7..31d1a9d539621 100644
--- a/src/plugins/vis_type_vislib/public/utils/common_config.tsx
+++ b/src/plugins/vis_type_xy/public/editor/common_config.tsx
@@ -20,36 +20,37 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
-import { PointSeriesOptions, MetricsAxisOptions } from '../components/options';
-import { ValidationWrapper } from '../components/common';
-import { BasicVislibParams } from '../types';
+import { VisOptionsProps } from '../../../vis_default_editor/public';
-function getAreaOptionTabs() {
+import { VisParams } from '../types';
+import { MetricsAxisOptions, PointSeriesOptions } from './components/options';
+import { ValidationWrapper } from './components/common';
+
+export function getOptionTabs(showElasticChartsOptions = false) {
return [
{
name: 'advanced',
- title: i18n.translate('visTypeVislib.area.tabs.metricsAxesTitle', {
+ title: i18n.translate('visTypeXy.area.tabs.metricsAxesTitle', {
defaultMessage: 'Metrics & axes',
}),
- editor: (props: VisOptionsProps) => (
+ editor: (props: VisOptionsProps) => (
),
},
{
name: 'options',
- title: i18n.translate('visTypeVislib.area.tabs.panelSettingsTitle', {
+ title: i18n.translate('visTypeXy.area.tabs.panelSettingsTitle', {
defaultMessage: 'Panel settings',
}),
- editor: (props: VisOptionsProps) => (
-
+ editor: (props: VisOptionsProps) => (
+
),
},
];
}
-
-const countLabel = i18n.translate('visTypeVislib.area.countText', {
- defaultMessage: 'Count',
-});
-
-export { getAreaOptionTabs, countLabel };
diff --git a/src/plugins/vis_type_vislib/public/components/common/index.ts b/src/plugins/vis_type_xy/public/editor/components/common/index.ts
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/common/index.ts
rename to src/plugins/vis_type_xy/public/editor/components/common/index.ts
diff --git a/src/plugins/vis_type_vislib/public/components/common/truncate_labels.tsx b/src/plugins/vis_type_xy/public/editor/components/common/truncate_labels.tsx
similarity index 96%
rename from src/plugins/vis_type_vislib/public/components/common/truncate_labels.tsx
rename to src/plugins/vis_type_xy/public/editor/components/common/truncate_labels.tsx
index 6f55f6f070d00..ae1f34376bbf8 100644
--- a/src/plugins/vis_type_vislib/public/components/common/truncate_labels.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/common/truncate_labels.tsx
@@ -33,7 +33,7 @@ function TruncateLabelsOption({ disabled, value = null, setValue }: TruncateLabe
return (
extends VisOptionsProps {
+export interface ValidationVisOptionsProps extends VisOptionsProps {
setMultipleValidity(paramName: string, isValid: boolean): void;
+ extraProps?: E;
}
-interface ValidationWrapperProps extends VisOptionsProps {
- component: React.ComponentType>;
+interface ValidationWrapperProps extends VisOptionsProps {
+ component: React.ComponentType>;
+ extraProps?: E;
}
interface Item {
isValid: boolean;
}
-function ValidationWrapper({
+function ValidationWrapper({
component: Component,
...rest
-}: ValidationWrapperProps) {
+}: ValidationWrapperProps) {
const [panelState, setPanelState] = useState({} as { [key: string]: Item });
const isPanelValid = Object.values(panelState).every((item) => item.isValid);
const { setValidity } = rest;
diff --git a/src/plugins/vis_type_vislib/public/components/index.ts b/src/plugins/vis_type_xy/public/editor/components/index.ts
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/index.ts
rename to src/plugins/vis_type_xy/public/editor/components/index.ts
diff --git a/src/plugins/vis_type_xy/public/editor/components/options/index.tsx b/src/plugins/vis_type_xy/public/editor/components/options/index.tsx
new file mode 100644
index 0000000000000..3eba7fa3ad818
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/editor/components/options/index.tsx
@@ -0,0 +1,39 @@
+/*
+ * 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 React, { lazy } from 'react';
+
+import { VisParams } from '../../../types';
+import { ValidationVisOptionsProps } from '../common';
+
+const PointSeriesOptionsLazy = lazy(() => import('./point_series'));
+const MetricsAxisOptionsLazy = lazy(() => import('./metrics_axes'));
+
+export const PointSeriesOptions = (
+ props: ValidationVisOptionsProps<
+ VisParams,
+ {
+ showElasticChartsOptions: boolean;
+ }
+ >
+) => ;
+
+export const MetricsAxisOptions = (props: ValidationVisOptionsProps) => (
+
+);
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap
similarity index 94%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap
index 2b7c03084ec65..bc66c1940ac72 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap
@@ -10,7 +10,7 @@ exports[`CategoryAxisPanel component should init with the default set of props 1
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap
similarity index 99%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap
index 09e0753d592e5..c5ce09d4d78af 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap
@@ -74,7 +74,6 @@ exports[`MetricsAxisOptions component should init with the default set of props
/>
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap
similarity index 98%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap
index ed7ae45eed3a5..594511010b745 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap
@@ -18,7 +18,7 @@ exports[`ValueAxesPanel component should init with the default set of props 1`]
@@ -120,7 +120,6 @@ exports[`ValueAxesPanel component should init with the default set of props 1`]
}
}
index={0}
- isCategoryAxisHorizontal={false}
onValueAxisPositionChanged={[MockFunction]}
setMultipleValidity={[MockFunction]}
setParamByIndex={[MockFunction]}
@@ -303,7 +302,6 @@ exports[`ValueAxesPanel component should init with the default set of props 1`]
}
}
index={1}
- isCategoryAxisHorizontal={false}
onValueAxisPositionChanged={[MockFunction]}
setMultipleValidity={[MockFunction]}
setParamByIndex={[MockFunction]}
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap
similarity index 96%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap
index c4142fb487b6a..3f3ee66a85924 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap
@@ -7,22 +7,18 @@ exports[`ValueAxisOptions component should init with the default set of props 1`
options={
Array [
Object {
- "disabled": false,
"text": "Top",
"value": "top",
},
Object {
- "disabled": true,
"text": "Left",
"value": "left",
},
Object {
- "disabled": true,
"text": "Right",
"value": "right",
},
Object {
- "disabled": false,
"text": "Bottom",
"value": "bottom",
},
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx
similarity index 93%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx
index 44ed0d5aeddab..3bf844618720b 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx
@@ -20,16 +20,16 @@
import React from 'react';
import { shallow } from 'enzyme';
import { CategoryAxisPanel, CategoryAxisPanelProps } from './category_axis_panel';
-import { Axis } from '../../../types';
-import { Positions } from '../../../utils/collections';
+import { CategoryAxis } from '../../../../types';
import { LabelOptions } from './label_options';
import { categoryAxis, vis } from './mocks';
+import { Position } from '@elastic/charts';
describe('CategoryAxisPanel component', () => {
let setCategoryAxis: jest.Mock;
let onPositionChanged: jest.Mock;
let defaultProps: CategoryAxisPanelProps;
- let axis: Axis;
+ let axis: CategoryAxis;
beforeEach(() => {
setCategoryAxis = jest.fn();
@@ -60,7 +60,7 @@ describe('CategoryAxisPanel component', () => {
});
it('should call onPositionChanged when position is changed', () => {
- const value = Positions.RIGHT;
+ const value = Position.Right;
const comp = shallow();
comp.find({ paramName: 'position' }).prop('setValue')('position', value);
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx
similarity index 78%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx
index 468fb1f8c315a..a551163747526 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx
@@ -19,20 +19,21 @@
import React, { useCallback } from 'react';
-import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
+import { Position } from '@elastic/charts';
+
+import { SelectOption, SwitchOption } from '../../../../../../charts/public';
+import { VisOptionsProps } from '../../../../../../vis_default_editor/public';
-import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
-import { Axis } from '../../../types';
-import { SelectOption, SwitchOption } from '../../../../../charts/public';
import { LabelOptions, SetAxisLabel } from './label_options';
-import { Positions } from '../../../utils/collections';
+import { CategoryAxis } from '../../../../types';
export interface CategoryAxisPanelProps {
- axis: Axis;
- onPositionChanged: (position: Positions) => void;
- setCategoryAxis: (value: Axis) => void;
+ axis: CategoryAxis;
+ onPositionChanged: (position: Position) => void;
+ setCategoryAxis: (value: CategoryAxis) => void;
vis: VisOptionsProps['vis'];
}
@@ -43,7 +44,7 @@ function CategoryAxisPanel({
setCategoryAxis,
}: CategoryAxisPanelProps) {
const setAxis = useCallback(
- (paramName: T, value: Axis[T]) => {
+ (paramName: T, value: CategoryAxis[T]) => {
const updatedAxis = {
...axis,
[paramName]: value,
@@ -54,7 +55,7 @@ function CategoryAxisPanel({
);
const setPosition = useCallback(
- (paramName: 'position', value: Axis['position']) => {
+ (paramName: 'position', value: CategoryAxis['position']) => {
setAxis(paramName, value);
onPositionChanged(value);
},
@@ -77,7 +78,7 @@ function CategoryAxisPanel({
@@ -85,7 +86,7 @@ function CategoryAxisPanel({
{
let setParamByIndex: jest.Mock;
@@ -53,14 +54,14 @@ describe('ChartOptions component', () => {
});
it('should show LineOptions when type is line', () => {
- chart.type = ChartTypes.LINE;
+ chart.type = ChartType.Line;
const comp = shallow();
expect(comp.find(LineOptions).exists()).toBeTruthy();
});
it('should show line mode when type is area', () => {
- chart.type = ChartTypes.AREA;
+ chart.type = ChartType.Area;
const comp = shallow();
expect(comp.find({ paramName: 'interpolate' }).exists()).toBeTruthy();
@@ -78,8 +79,8 @@ describe('ChartOptions component', () => {
it('should call setParamByIndex when mode is changed', () => {
const comp = shallow();
const paramName = 'mode';
- comp.find({ paramName }).prop('setValue')(paramName, ChartModes.NORMAL);
+ comp.find({ paramName }).prop('setValue')(paramName, ChartMode.Normal);
- expect(setParamByIndex).toBeCalledWith('seriesParams', 0, paramName, ChartModes.NORMAL);
+ expect(setParamByIndex).toBeCalledWith('seriesParams', 0, paramName, ChartMode.Normal);
});
});
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/chart_options.tsx
similarity index 80%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/chart_options.tsx
index 623a8d1f348e9..c379fa30b49b8 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/chart_options.tsx
@@ -22,12 +22,13 @@ import React, { useMemo, useCallback } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
-import { Vis } from '../../../../../visualizations/public';
-import { SeriesParam, ValueAxis } from '../../../types';
-import { ChartTypes } from '../../../utils/collections';
-import { SelectOption } from '../../../../../charts/public';
+import { Vis } from '../../../../../../visualizations/public';
+import { SelectOption } from '../../../../../../charts/public';
+
+import { SeriesParam, ValueAxis } from '../../../../types';
import { LineOptions } from './line_options';
import { SetParamByIndex, ChangeValueAxis } from '.';
+import { ChartType } from '../../../../../common';
export type SetChart = (paramName: T, value: SeriesParam[T]) => void;
@@ -69,7 +70,7 @@ function ChartOptions({
value: id,
})),
{
- text: i18n.translate('visTypeVislib.controls.pointSeries.series.newAxisLabel', {
+ text: i18n.translate('visTypeXy.controls.pointSeries.series.newAxisLabel', {
defaultMessage: 'New axis…',
}),
value: 'new',
@@ -82,7 +83,7 @@ function ChartOptions({
<>
- {chart.type === ChartTypes.AREA && (
+ {chart.type === ChartType.Area && (
<>
)}
- {chart.type === ChartTypes.LINE && (
-
- )}
+ {chart.type === ChartType.Line && }
>
);
}
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.test.tsx
similarity index 99%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.test.tsx
index 4798c67928f7f..82097271f8814 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.test.tsx
@@ -19,6 +19,7 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
+
import { CustomExtentsOptions, CustomExtentsOptionsProps } from './custom_extents_options';
import { YExtents } from './y_extents';
import { valueAxis } from './mocks';
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.tsx
similarity index 87%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.tsx
index 634d6b3f0641c..86a0c56e46942 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/custom_extents_options.tsx
@@ -18,10 +18,12 @@
*/
import React, { useCallback, useEffect } from 'react';
+
import { i18n } from '@kbn/i18n';
-import { ValueAxis } from '../../../types';
-import { NumberInputOption, SwitchOption } from '../../../../../charts/public';
+import { NumberInputOption, SwitchOption } from '../../../../../../charts/public';
+
+import { ValueAxis } from '../../../../types';
import { YExtents } from './y_extents';
import { SetScale } from './value_axis_options';
@@ -39,7 +41,7 @@ function CustomExtentsOptions({
setValueAxisScale,
}: CustomExtentsOptionsProps) {
const invalidBoundsMarginMessage = i18n.translate(
- 'visTypeVislib.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin',
+ 'visTypeXy.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin',
{ defaultMessage: 'Bounds margin must be greater than or equal to 0.' }
);
@@ -84,12 +86,9 @@ function CustomExtentsOptions({
return (
<>
({
+ SeriesPanel: () => 'SeriesPanel',
+}));
+jest.mock('./category_axis_panel', () => ({
+ CategoryAxisPanel: () => 'CategoryAxisPanel',
+}));
+jest.mock('./value_axes_panel', () => ({
+ ValueAxesPanel: () => 'ValueAxesPanel',
+}));
+
+const SERIES_PARAMS = 'seriesParams';
+const VALUE_AXES = 'valueAxes';
+
+const aggCount: IAggConfig = {
+ id: '1',
+ type: { name: 'count' },
+ makeLabel: () => 'Count',
+} as IAggConfig;
+
+const aggAverage: IAggConfig = {
+ id: '2',
+ type: { name: 'average' } as IAggType,
+ makeLabel: () => 'Average',
+} as IAggConfig;
+
+const createAggs = (aggs: any[]) => ({
+ aggs,
+ bySchemaName: () => aggs,
+});
+
+describe('MetricsAxisOptions component', () => {
+ let setValue: jest.Mock;
+ let defaultProps: ValidationVisOptionsProps;
+ let axis: ValueAxis;
+ let axisRight: ValueAxis;
+ let chart: SeriesParam;
+
+ beforeEach(() => {
+ setValue = jest.fn();
+
+ axis = {
+ ...valueAxis,
+ name: 'LeftAxis-1',
+ position: Position.Left,
+ };
+ axisRight = {
+ ...valueAxis,
+ id: 'ValueAxis-2',
+ name: 'RightAxis-1',
+ position: Position.Right,
+ };
+ chart = {
+ ...seriesParam,
+ type: ChartType.Area,
+ };
+
+ defaultProps = {
+ aggs: createAggs([aggCount]),
+ isTabSelected: true,
+ vis: {
+ type: {
+ type: ChartType.Area,
+ schemas: { metrics: [{ name: 'metric' }] },
+ },
+ setState: jest.fn(),
+ serialize: jest.fn(),
+ },
+ stateParams: {
+ valueAxes: [axis],
+ seriesParams: [chart],
+ categoryAxes: [categoryAxis],
+ grid: {
+ valueAxis: defaultValueAxisId,
+ },
+ },
+ setValue,
+ } as any;
+ });
+
+ it('should init with the default set of props', () => {
+ const component = shallow();
+
+ expect(component).toMatchSnapshot();
+ });
+
+ describe('useEffect', () => {
+ it('should update series when new agg is added', () => {
+ const component = mount();
+ component.setProps({
+ aggs: createAggs([aggCount, aggAverage]),
+ });
+
+ const updatedSeries = [chart, { ...chart, data: { id: '2', label: aggAverage.makeLabel() } }];
+ expect(setValue).toHaveBeenLastCalledWith(SERIES_PARAMS, updatedSeries);
+ });
+
+ it('should update series when new agg label is changed', () => {
+ const component = mount();
+ const agg = { id: aggCount.id, makeLabel: () => 'New label' };
+ component.setProps({
+ aggs: createAggs([agg]),
+ });
+
+ const updatedSeries = [{ ...chart, data: { id: agg.id, label: agg.makeLabel() } }];
+ expect(setValue).toHaveBeenCalledWith(SERIES_PARAMS, updatedSeries);
+ });
+ });
+
+ describe('updateAxisTitle', () => {
+ it('should not update the value axis title if custom title was set', () => {
+ defaultProps.stateParams.valueAxes[0].title.text = 'Custom title';
+ const component = mount();
+ const newAgg = {
+ ...aggCount,
+ makeLabel: () => 'Custom label',
+ };
+ component.setProps({
+ aggs: createAggs([newAgg]),
+ });
+ const updatedValues = [{ ...axis, title: { text: newAgg.makeLabel() } }];
+ expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES, updatedValues);
+ });
+
+ it('should set the custom title to match the value axis label when only one agg exists for that axis', () => {
+ const component = mount();
+ const agg = {
+ id: aggCount.id,
+ params: { customLabel: 'Custom label' },
+ makeLabel: () => 'Custom label',
+ };
+ component.setProps({
+ aggs: createAggs([agg]),
+ });
+
+ const updatedSeriesParams = [{ ...chart, data: { ...chart.data, label: agg.makeLabel() } }];
+ const updatedValues = [{ ...axis, title: { text: agg.makeLabel() } }];
+
+ expect(setValue).toHaveBeenCalledTimes(5);
+ expect(setValue).toHaveBeenNthCalledWith(3, SERIES_PARAMS, updatedSeriesParams);
+ expect(setValue).toHaveBeenNthCalledWith(5, SERIES_PARAMS, updatedSeriesParams);
+ expect(setValue).toHaveBeenNthCalledWith(4, VALUE_AXES, updatedValues);
+ });
+
+ it('should not set the custom title to match the value axis label when more than one agg exists for that axis', () => {
+ const component = mount();
+ const agg = { id: aggCount.id, makeLabel: () => 'Custom label' };
+ component.setProps({
+ aggs: createAggs([agg, aggAverage]),
+ stateParams: {
+ ...defaultProps.stateParams,
+ seriesParams: [chart, chart],
+ },
+ });
+
+ expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES);
+ });
+
+ it('should not overwrite the custom title with the value axis label if the custom title has been changed', () => {
+ defaultProps.stateParams.valueAxes[0].title.text = 'Custom title';
+ const component = mount();
+ const agg = {
+ id: aggCount.id,
+ params: { customLabel: 'Custom label' },
+ makeLabel: () => 'Custom label',
+ };
+ component.setProps({
+ aggs: createAggs([agg]),
+ });
+
+ expect(setValue).not.toHaveBeenCalledWith(VALUE_AXES);
+ });
+ });
+
+ it('should add value axis', () => {
+ const component = shallow();
+ component.find(ValueAxesPanel).prop('addValueAxis')();
+
+ expect(setValue).toHaveBeenCalledWith(VALUE_AXES, [axis, axisRight]);
+ });
+
+ describe('removeValueAxis', () => {
+ beforeEach(() => {
+ defaultProps.stateParams.valueAxes = [axis, axisRight];
+ });
+
+ it('should remove value axis', () => {
+ const component = shallow();
+ component.find(ValueAxesPanel).prop('removeValueAxis')(axis);
+
+ expect(setValue).toHaveBeenCalledWith(VALUE_AXES, [axisRight]);
+ });
+
+ it('should update seriesParams "valueAxis" prop', () => {
+ const updatedSeriesParam = { ...chart, valueAxis: 'ValueAxis-2' };
+ const component = shallow();
+ component.find(ValueAxesPanel).prop('removeValueAxis')(axis);
+
+ expect(setValue).toHaveBeenCalledWith(SERIES_PARAMS, [updatedSeriesParam]);
+ });
+
+ it('should reset grid "valueAxis" prop', () => {
+ const updatedGrid = { valueAxis: undefined };
+ defaultProps.stateParams.seriesParams[0].valueAxis = 'ValueAxis-2';
+ const component = shallow();
+ component.find(ValueAxesPanel).prop('removeValueAxis')(axis);
+
+ expect(setValue).toHaveBeenCalledWith('grid', updatedGrid);
+ });
+ });
+
+ describe('onValueAxisPositionChanged', () => {
+ const getProps = (
+ valuePosition1: Position = Position.Right,
+ valuePosition2: Position = Position.Left
+ ): ValidationVisOptionsProps => ({
+ ...defaultProps,
+ stateParams: {
+ ...defaultProps.stateParams,
+ valueAxes: [
+ {
+ ...valueAxis,
+ id: 'ValueAxis-1',
+ position: valuePosition1,
+ },
+ {
+ ...valueAxis,
+ id: 'ValueAxis-2',
+ position: valuePosition2,
+ },
+ {
+ ...valueAxis,
+ id: 'ValueAxis-3',
+ position: valuePosition2,
+ },
+ ],
+ categoryAxes: [
+ {
+ ...categoryAxis,
+ position: mapPosition(valuePosition1),
+ },
+ ],
+ },
+ });
+
+ it('should update all value axes if another value axis changes from horizontal to vertical', () => {
+ const component = mount();
+ setValue.mockClear();
+ const onValueAxisPositionChanged = component
+ .find(ValueAxesPanel)
+ .prop('onValueAxisPositionChanged');
+ onValueAxisPositionChanged(0, Position.Bottom);
+ expect(setValue).nthCalledWith(1, 'categoryAxes', [
+ expect.objectContaining({
+ id: 'CategoryAxis-1',
+ position: Position.Right,
+ }),
+ ]);
+ expect(setValue).nthCalledWith(2, 'valueAxes', [
+ expect.objectContaining({
+ id: 'ValueAxis-1',
+ position: Position.Bottom,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-2',
+ position: Position.Top,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-3',
+ position: Position.Top,
+ }),
+ ]);
+ });
+
+ it('should update all value axes if another value axis changes from vertical to horizontal', () => {
+ const component = mount();
+ setValue.mockClear();
+ const onValueAxisPositionChanged = component
+ .find(ValueAxesPanel)
+ .prop('onValueAxisPositionChanged');
+ onValueAxisPositionChanged(1, Position.Left);
+ expect(setValue).nthCalledWith(1, 'categoryAxes', [
+ expect.objectContaining({
+ id: 'CategoryAxis-1',
+ position: Position.Top,
+ }),
+ ]);
+ expect(setValue).nthCalledWith(2, 'valueAxes', [
+ expect.objectContaining({
+ id: 'ValueAxis-1',
+ position: Position.Right,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-2',
+ position: Position.Left,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-3',
+ position: Position.Left,
+ }),
+ ]);
+ });
+
+ it('should update only changed value axis if value axis stays horizontal', () => {
+ const component = mount();
+ setValue.mockClear();
+ const onValueAxisPositionChanged = component
+ .find(ValueAxesPanel)
+ .prop('onValueAxisPositionChanged');
+ onValueAxisPositionChanged(0, Position.Left);
+ expect(setValue).nthCalledWith(1, 'valueAxes', [
+ expect.objectContaining({
+ id: 'ValueAxis-1',
+ position: Position.Left,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-2',
+ position: Position.Left,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-3',
+ position: Position.Left,
+ }),
+ ]);
+ });
+
+ it('should update only changed value axis if value axis stays vertical', () => {
+ const component = mount();
+ setValue.mockClear();
+ const onValueAxisPositionChanged = component
+ .find(ValueAxesPanel)
+ .prop('onValueAxisPositionChanged');
+ onValueAxisPositionChanged(1, Position.Top);
+ expect(setValue).nthCalledWith(1, 'valueAxes', [
+ expect.objectContaining({
+ id: 'ValueAxis-1',
+ position: Position.Top,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-2',
+ position: Position.Top,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-3',
+ position: Position.Bottom,
+ }),
+ ]);
+ });
+ });
+
+ describe('onCategoryAxisPositionChanged', () => {
+ const getProps = (
+ position: Position = Position.Bottom
+ ): ValidationVisOptionsProps => ({
+ ...defaultProps,
+ stateParams: {
+ ...defaultProps.stateParams,
+ valueAxes: [
+ {
+ ...valueAxis,
+ id: 'ValueAxis-1',
+ position: mapPosition(position),
+ },
+ {
+ ...valueAxis,
+ id: 'ValueAxis-2',
+ position: mapPositionOpposite(mapPosition(position)),
+ },
+ {
+ ...valueAxis,
+ id: 'ValueAxis-3',
+ position: mapPosition(position),
+ },
+ ],
+ categoryAxes: [
+ {
+ ...categoryAxis,
+ position,
+ },
+ ],
+ },
+ });
+
+ it('should update all value axes if category axis changes from horizontal to vertical', () => {
+ const component = mount();
+ setValue.mockClear();
+ const onPositionChanged = component.find(CategoryAxisPanel).prop('onPositionChanged');
+ onPositionChanged(Position.Left);
+ expect(setValue).nthCalledWith(1, 'valueAxes', [
+ expect.objectContaining({
+ id: 'ValueAxis-1',
+ position: Position.Bottom,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-2',
+ position: Position.Top,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-3',
+ position: Position.Bottom,
+ }),
+ ]);
+ });
+
+ it('should update all value axes if category axis changes from vertical to horizontal', () => {
+ const component = mount();
+ setValue.mockClear();
+ const onPositionChanged = component.find(CategoryAxisPanel).prop('onPositionChanged');
+ onPositionChanged(Position.Top);
+ expect(setValue).nthCalledWith(1, 'valueAxes', [
+ expect.objectContaining({
+ id: 'ValueAxis-1',
+ position: Position.Left,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-2',
+ position: Position.Right,
+ }),
+ expect.objectContaining({
+ id: 'ValueAxis-3',
+ position: Position.Left,
+ }),
+ ]);
+ });
+
+ it('should not update value axes if category axis stays horizontal', () => {
+ const component = mount();
+ setValue.mockClear();
+ const onPositionChanged = component.find(CategoryAxisPanel).prop('onPositionChanged');
+ onPositionChanged(Position.Top);
+ expect(setValue).not.toBeCalled();
+ });
+
+ it('should not update value axes if category axis stays vertical', () => {
+ const component = mount();
+ setValue.mockClear();
+ const onPositionChanged = component.find(CategoryAxisPanel).prop('onPositionChanged');
+ onPositionChanged(Position.Right);
+ expect(setValue).not.toBeCalled();
+ });
+ });
+});
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/index.tsx
similarity index 83%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/index.tsx
index 0862c47c35cff..9b4bf3127d45e 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/index.tsx
@@ -19,10 +19,12 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { cloneDeep, get } from 'lodash';
+
import { EuiSpacer } from '@elastic/eui';
-import { IAggConfig } from 'src/plugins/data/public';
-import { BasicVislibParams, ValueAxis, SeriesParam, Axis } from '../../../types';
+import { IAggConfig } from '../../../../../../data/public';
+
+import { VisParams, ValueAxis, SeriesParam, CategoryAxis } from '../../../../types';
import { ValidationVisOptionsProps } from '../../common';
import { SeriesPanel } from './series_panel';
import { CategoryAxisPanel } from './category_axis_panel';
@@ -34,6 +36,7 @@ import {
getUpdatedAxisName,
mapPositionOpposite,
mapPosition,
+ mapPositionOpposingOpposite,
} from './utils';
export type SetParamByIndex = (
@@ -51,11 +54,9 @@ export type ChangeValueAxis = (
const VALUE_AXIS_PREFIX = 'ValueAxis-';
-function MetricsAxisOptions(props: ValidationVisOptionsProps) {
+function MetricsAxisOptions(props: ValidationVisOptionsProps) {
const { stateParams, setValue, aggs, vis, isTabSelected } = props;
- const [isCategoryAxisHorizontal, setIsCategoryAxisHorizontal] = useState(true);
-
const setParamByIndex: SetParamByIndex = useCallback(
(axesName, index, paramName, value) => {
const items = stateParams[axesName];
@@ -72,7 +73,7 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps)
);
const setCategoryAxis = useCallback(
- (value: Axis) => {
+ (value: CategoryAxis) => {
const categoryAxes = [...stateParams.categoryAxes];
categoryAxes[0] = value;
setValue('categoryAxes', categoryAxes);
@@ -170,33 +171,58 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps)
);
const onValueAxisPositionChanged = useCallback(
- (index: number, value: ValueAxis['position']) => {
+ (index: number, axisPosition: ValueAxis['position']) => {
+ const isHorizontalAxis = isAxisHorizontal(axisPosition);
const valueAxes = [...stateParams.valueAxes];
- const name = getUpdatedAxisName(value, valueAxes);
+ const name = getUpdatedAxisName(axisPosition, valueAxes);
+ const [categoryAxes] = stateParams.categoryAxes;
- valueAxes[index] = {
- ...valueAxes[index],
- name,
- position: value,
- };
- setValue('valueAxes', valueAxes);
+ if (isAxisHorizontal(categoryAxes.position) === isHorizontalAxis) {
+ const updatedCategoryAxes = {
+ ...categoryAxes,
+ position: mapPosition(categoryAxes.position),
+ };
+
+ setValue('categoryAxes', [updatedCategoryAxes]);
+
+ const oldPosition = valueAxes[index].position;
+ const newValueAxes = valueAxes.map(({ position, ...axis }, i) => ({
+ ...axis,
+ position:
+ i === index
+ ? axisPosition
+ : mapPositionOpposingOpposite(position, oldPosition, axisPosition),
+ }));
+ setValue('valueAxes', newValueAxes);
+ } else {
+ valueAxes[index] = {
+ ...valueAxes[index],
+ name,
+ position: axisPosition,
+ };
+ setValue('valueAxes', valueAxes);
+ }
},
- [stateParams.valueAxes, setValue]
+ [stateParams.valueAxes, stateParams.categoryAxes, setValue]
);
const onCategoryAxisPositionChanged = useCallback(
- (chartPosition: Axis['position']) => {
- const isChartHorizontal = isAxisHorizontal(chartPosition);
- setIsCategoryAxisHorizontal(isAxisHorizontal(chartPosition));
-
- stateParams.valueAxes.forEach((axis, index) => {
- if (isAxisHorizontal(axis.position) === isChartHorizontal) {
- const position = mapPosition(axis.position);
- onValueAxisPositionChanged(index, position);
- }
- });
+ (axisPosition: CategoryAxis['position']) => {
+ const isHorizontalAxis = isAxisHorizontal(axisPosition);
+
+ if (
+ stateParams.valueAxes.some(
+ ({ position }) => isAxisHorizontal(position) === isHorizontalAxis
+ )
+ ) {
+ const newValueAxes = stateParams.valueAxes.map(({ position, ...axis }) => ({
+ ...axis,
+ position: mapPosition(position),
+ }));
+ setValue('valueAxes', newValueAxes);
+ }
},
- [stateParams.valueAxes, onValueAxisPositionChanged]
+ [setValue, stateParams.valueAxes]
);
const addValueAxis = useCallback(() => {
@@ -305,7 +331,6 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps)
(
- paramName: T,
- value: Axis['labels'][T]
-) => void;
+export type SetAxisLabel = (paramName: T, value: Labels[T]) => void;
export interface LabelOptionsProps {
- axisLabels: Axis['labels'];
+ axisLabels: Labels;
axisFilterCheckboxName: string;
setAxisLabel: SetAxisLabel;
}
function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: LabelOptionsProps) {
const setAxisLabelRotate = useCallback(
- (paramName: 'rotate', value: Axis['labels']['rotate']) => {
+ (paramName: 'rotate', value: Labels['rotate']) => {
setAxisLabel(paramName, Number(value));
},
[setAxisLabel]
@@ -54,7 +51,7 @@ function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: Labe
@@ -62,7 +59,7 @@ function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: Labe
@@ -57,13 +58,10 @@ function SeriesPanel({ seriesParams, ...chartProps }: SeriesPanelProps) {
initialIsOpen={index === 0}
buttonContent={chart.data.label}
buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate"
- aria-label={i18n.translate(
- 'visTypeVislib.controls.pointSeries.seriesAccordionAriaLabel',
- {
- defaultMessage: 'Toggle {agg} options',
- values: { agg: chart.data.label },
- }
- )}
+ aria-label={i18n.translate('visTypeXy.controls.pointSeries.seriesAccordionAriaLabel', {
+ defaultMessage: 'Toggle {agg} options',
+ values: { agg: chart.data.label },
+ })}
>
<>
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/utils.ts
similarity index 53%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/utils.ts
index 708e8cf15f029..58216ee8953cd 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/utils.ts
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-
import { upperFirst } from 'lodash';
-import { BasicVislibParams, ValueAxis, SeriesParam } from '../../../types';
-import { ChartModes, ChartTypes, InterpolationModes, Positions } from '../../../utils/collections';
+import { Position } from '@elastic/charts';
+
+import { VisParams, ValueAxis, SeriesParam, ChartMode, InterpolationMode } from '../../../../types';
+import { ChartType } from '../../../../../common';
-const makeSerie = (
+export const makeSerie = (
id: string,
label: string,
defaultValueAxis: ValueAxis['id'],
@@ -31,11 +32,11 @@ const makeSerie = (
const data = { id, label };
const defaultSerie = {
show: true,
- mode: ChartModes.NORMAL,
- type: ChartTypes.LINE,
+ mode: ChartMode.Normal,
+ type: ChartType.Line,
drawLinesBetweenPoints: true,
showCircles: true,
- interpolate: InterpolationModes.LINEAR,
+ interpolate: InterpolationMode.Linear,
lineWidth: 2,
valueAxis: defaultValueAxis,
data,
@@ -43,12 +44,12 @@ const makeSerie = (
return lastSerie ? { ...lastSerie, data } : defaultSerie;
};
-const isAxisHorizontal = (position: Positions) =>
- [Positions.TOP, Positions.BOTTOM].includes(position as any);
+export const isAxisHorizontal = (position: Position) =>
+ [Position.Top, Position.Bottom].includes(position as any);
const RADIX = 10;
-function countNextAxisNumber(axisName: string, axisProp: 'id' | 'name' = 'id') {
+export function countNextAxisNumber(axisName: string, axisProp: 'id' | 'name' = 'id') {
return (value: number, axis: ValueAxis) => {
const nameLength = axisName.length;
if (axis[axisProp].substr(0, nameLength) === axisName) {
@@ -63,9 +64,9 @@ function countNextAxisNumber(axisName: string, axisProp: 'id' | 'name' = 'id') {
const AXIS_PREFIX = 'Axis-';
-const getUpdatedAxisName = (
+export const getUpdatedAxisName = (
axisPosition: ValueAxis['position'],
- valueAxes: BasicVislibParams['valueAxes']
+ valueAxes: VisParams['valueAxes']
) => {
const axisName = upperFirst(axisPosition) + AXIS_PREFIX;
const nextAxisNameNumber = valueAxes.reduce(countNextAxisNumber(axisName, 'name'), 1);
@@ -73,39 +74,56 @@ const getUpdatedAxisName = (
return `${axisName}${nextAxisNameNumber}`;
};
-function mapPositionOpposite(position: Positions) {
+/**
+ * Maps axis position to opposite position
+ * @param position
+ */
+export function mapPositionOpposite(position: Position) {
switch (position) {
- case Positions.BOTTOM:
- return Positions.TOP;
- case Positions.TOP:
- return Positions.BOTTOM;
- case Positions.LEFT:
- return Positions.RIGHT;
- case Positions.RIGHT:
- return Positions.LEFT;
+ case Position.Bottom:
+ return Position.Top;
+ case Position.Top:
+ return Position.Bottom;
+ case Position.Left:
+ return Position.Right;
+ case Position.Right:
+ return Position.Left;
default:
throw new Error('Invalid legend position.');
}
}
-function mapPosition(position: Positions) {
- switch (position) {
- case Positions.BOTTOM:
- return Positions.LEFT;
- case Positions.TOP:
- return Positions.RIGHT;
- case Positions.LEFT:
- return Positions.BOTTOM;
- case Positions.RIGHT:
- return Positions.TOP;
+/**
+ * Maps axis position to new position or opposite of new position based on old position
+ * @param position
+ * @param oldPosition
+ * @param newPosition
+ */
+export function mapPositionOpposingOpposite(
+ position: Position,
+ oldPosition: Position,
+ newPosition: Position
+) {
+ if (position === oldPosition) {
+ return newPosition;
}
+
+ return mapPositionOpposite(newPosition);
}
-export {
- makeSerie,
- isAxisHorizontal,
- countNextAxisNumber,
- getUpdatedAxisName,
- mapPositionOpposite,
- mapPosition,
-};
+/**
+ * Maps axis position to opposite rotation position
+ * @param position
+ */
+export function mapPosition(position: Position) {
+ switch (position) {
+ case Position.Bottom:
+ return Position.Left;
+ case Position.Top:
+ return Position.Right;
+ case Position.Left:
+ return Position.Bottom;
+ case Position.Right:
+ return Position.Top;
+ }
+}
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.test.tsx
similarity index 96%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.test.tsx
index 070433ca03f6d..f3286029db32f 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.test.tsx
@@ -19,10 +19,12 @@
import React from 'react';
import { shallow } from 'enzyme';
-import { ValueAxesPanel, ValueAxesPanelProps } from './value_axes_panel';
-import { ValueAxis, SeriesParam } from '../../../types';
-import { Positions } from '../../../utils/collections';
+
import { mountWithIntl } from '@kbn/test/jest';
+import { Position } from '@elastic/charts';
+
+import { ValueAxis, SeriesParam } from '../../../../types';
+import { ValueAxesPanel, ValueAxesPanelProps } from './value_axes_panel';
import { valueAxis, seriesParam, vis } from './mocks';
describe('ValueAxesPanel component', () => {
@@ -47,7 +49,7 @@ describe('ValueAxesPanel component', () => {
axisRight = {
...valueAxis,
id: 'ValueAxis-2',
- position: Positions.RIGHT,
+ position: Position.Right,
};
seriesParamCount = { ...seriesParam };
seriesParamAverage = {
@@ -63,7 +65,6 @@ describe('ValueAxesPanel component', () => {
seriesParams: [seriesParamCount, seriesParamAverage],
valueAxes: [axisLeft, axisRight],
vis,
- isCategoryAxisHorizontal: false,
setParamByIndex,
onValueAxisPositionChanged,
addValueAxis,
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.tsx
similarity index 90%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.tsx
index 5f7d33b7f1f47..397704663ff1f 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axes_panel.tsx
@@ -31,13 +31,13 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { Vis } from '../../../../../visualizations/public';
-import { SeriesParam, ValueAxis } from '../../../types';
+import { Vis } from '../../../../../../visualizations/public';
+
+import { SeriesParam, ValueAxis } from '../../../../types';
import { ValueAxisOptions } from './value_axis_options';
import { SetParamByIndex } from '.';
export interface ValueAxesPanelProps {
- isCategoryAxisHorizontal: boolean;
addValueAxis: () => ValueAxis;
removeValueAxis: (axis: ValueAxis) => void;
onValueAxisPositionChanged: (index: number, value: ValueAxis['position']) => void;
@@ -64,7 +64,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) {
const removeButtonTooltip = useMemo(
() =>
- i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.removeButtonTooltip', {
+ i18n.translate('visTypeXy.controls.pointSeries.valueAxes.removeButtonTooltip', {
defaultMessage: 'Remove Y-axis',
}),
[]
@@ -87,7 +87,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) {
const addButtonTooltip = useMemo(
() =>
- i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.addButtonTooltip', {
+ i18n.translate('visTypeXy.controls.pointSeries.valueAxes.addButtonTooltip', {
defaultMessage: 'Add Y-axis',
}),
[]
@@ -115,7 +115,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) {
@@ -146,7 +146,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) {
buttonClassName="eui-textTruncate"
buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate"
aria-label={i18n.translate(
- 'visTypeVislib.controls.pointSeries.valueAxes.toggleOptionsAriaLabel',
+ 'visTypeXy.controls.pointSeries.valueAxes.toggleOptionsAriaLabel',
{
defaultMessage: 'Toggle {axisName} options',
values: { axisName: axis.name },
@@ -160,7 +160,6 @@ function ValueAxesPanel(props: ValueAxesPanelProps) {
axis={axis}
index={index}
valueAxis={valueAxes[index]}
- isCategoryAxisHorizontal={props.isCategoryAxisHorizontal}
onValueAxisPositionChanged={props.onValueAxisPositionChanged}
setParamByIndex={props.setParamByIndex}
setMultipleValidity={props.setMultipleValidity}
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.test.tsx
similarity index 64%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.test.tsx
index 1977bdba6eadf..0b325198c3fe7 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.test.tsx
@@ -19,21 +19,18 @@
import React from 'react';
import { shallow } from 'enzyme';
-import { ValueAxisOptions, ValueAxisOptionsParams } from './value_axis_options';
-import { ValueAxis } from '../../../types';
-import { TextInputOption } from '../../../../../charts/public';
+
+import { Position } from '@elastic/charts';
+
+import { TextInputOption } from '../../../../../../charts/public';
+
+import { ValueAxis, ScaleType } from '../../../../types';
import { LabelOptions } from './label_options';
-import { ScaleTypes, Positions } from '../../../utils/collections';
+import { ValueAxisOptions, ValueAxisOptionsParams } from './value_axis_options';
import { valueAxis, vis } from './mocks';
const POSITION = 'position';
-interface PositionOption {
- text: string;
- value: Positions;
- disabled: boolean;
-}
-
describe('ValueAxisOptions component', () => {
let setParamByIndex: jest.Mock;
let onValueAxisPositionChanged: jest.Mock;
@@ -52,7 +49,6 @@ describe('ValueAxisOptions component', () => {
index: 0,
valueAxis,
vis,
- isCategoryAxisHorizontal: false,
setParamByIndex,
onValueAxisPositionChanged,
setMultipleValidity,
@@ -73,50 +69,8 @@ describe('ValueAxisOptions component', () => {
expect(comp.find(LabelOptions).exists()).toBeFalsy();
});
- it('should only allow left and right value axis position when category axis is horizontal', () => {
- defaultProps.isCategoryAxisHorizontal = true;
- const comp = shallow();
-
- const options: PositionOption[] = comp.find({ paramName: POSITION }).prop('options');
-
- expect(options.length).toBe(4);
- options.forEach(({ value, disabled }) => {
- switch (value) {
- case Positions.LEFT:
- case Positions.RIGHT:
- expect(disabled).toBeFalsy();
- break;
- case Positions.TOP:
- case Positions.BOTTOM:
- expect(disabled).toBeTruthy();
- break;
- }
- });
- });
-
- it('should only allow top and bottom value axis position when category axis is vertical', () => {
- defaultProps.isCategoryAxisHorizontal = false;
- const comp = shallow();
-
- const options: PositionOption[] = comp.find({ paramName: POSITION }).prop('options');
-
- expect(options.length).toBe(4);
- options.forEach(({ value, disabled }) => {
- switch (value) {
- case Positions.LEFT:
- case Positions.RIGHT:
- expect(disabled).toBeTruthy();
- break;
- case Positions.TOP:
- case Positions.BOTTOM:
- expect(disabled).toBeFalsy();
- break;
- }
- });
- });
-
it('should call onValueAxisPositionChanged when position is changed', () => {
- const value = Positions.RIGHT;
+ const value = Position.Right;
const comp = shallow();
comp.find({ paramName: POSITION }).prop('setValue')(POSITION, value);
@@ -135,7 +89,7 @@ describe('ValueAxisOptions component', () => {
});
it('should call setValueAxis when scale value is changed', () => {
- const scaleValue = ScaleTypes.SQUARE_ROOT;
+ const scaleValue = ScaleType.SquareRoot;
const comp = shallow();
comp.find({ paramName: 'type' }).prop('setValue')('type', scaleValue);
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.tsx
similarity index 76%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.tsx
index b42d038267d77..4ab792142e83a 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/value_axis_options.tsx
@@ -17,17 +17,16 @@
* under the License.
*/
-import React, { useCallback, useMemo } from 'react';
+import React, { useCallback } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiSpacer, EuiAccordion, EuiHorizontalRule } from '@elastic/eui';
-import { Vis } from '../../../../../visualizations/public';
-import { ValueAxis } from '../../../types';
-import { Positions } from '../../../utils/collections';
-import { SelectOption, SwitchOption, TextInputOption } from '../../../../../charts/public';
+import { Vis } from '../../../../../../visualizations/public';
+import { SelectOption, SwitchOption, TextInputOption } from '../../../../../../charts/public';
+
+import { ValueAxis } from '../../../../types';
import { LabelOptions, SetAxisLabel } from './label_options';
import { CustomExtentsOptions } from './custom_extents_options';
-import { isAxisHorizontal } from './utils';
import { SetParamByIndex } from '.';
export type SetScale = (
@@ -38,7 +37,6 @@ export type SetScale = (
export interface ValueAxisOptionsParams {
axis: ValueAxis;
index: number;
- isCategoryAxisHorizontal: boolean;
onValueAxisPositionChanged: (index: number, value: ValueAxis['position']) => void;
setParamByIndex: SetParamByIndex;
valueAxis: ValueAxis;
@@ -46,10 +44,9 @@ export interface ValueAxisOptionsParams {
setMultipleValidity: (paramName: string, isValid: boolean) => void;
}
-function ValueAxisOptions({
+export function ValueAxisOptions({
axis,
index,
- isCategoryAxisHorizontal,
valueAxis,
vis,
onValueAxisPositionChanged,
@@ -105,34 +102,13 @@ function ValueAxisOptions({
[index, onValueAxisPositionChanged]
);
- const isPositionDisabled = useCallback(
- (position: Positions) => {
- if (isCategoryAxisHorizontal) {
- return isAxisHorizontal(position);
- }
- return [Positions.LEFT, Positions.RIGHT].includes(position as any);
- },
- [isCategoryAxisHorizontal]
- );
-
- const positions = useMemo(
- () =>
- vis.type.editorConfig.collections.positions.map(
- (position: { text: string; value: Positions }) => ({
- ...position,
- disabled: isPositionDisabled(position.value),
- })
- ),
- [vis.type.editorConfig.collections.positions, isPositionDisabled]
- );
-
return (
<>
);
}
-
-export { ValueAxisOptions };
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.test.tsx
similarity index 94%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.test.tsx
index 7bd5c9efdf29d..c2af7f2ad921b 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.test.tsx
@@ -19,9 +19,11 @@
import React from 'react';
import { mount, shallow } from 'enzyme';
+
+import { NumberInputOption } from '../../../../../../charts/public';
+
+import { ScaleType } from '../../../../types';
import { YExtents, YExtentsProps } from './y_extents';
-import { ScaleTypes } from '../../../utils/collections';
-import { NumberInputOption } from '../../../../../charts/public';
describe('YExtents component', () => {
let setMultipleValidity: jest.Mock;
@@ -35,7 +37,7 @@ describe('YExtents component', () => {
defaultProps = {
scale: {
- type: ScaleTypes.LINEAR,
+ type: ScaleType.Linear,
},
setMultipleValidity,
setScale,
@@ -81,7 +83,7 @@ describe('YExtents component', () => {
it('should call setMultipleValidity with false when min equals 0 and scale is log', () => {
defaultProps.scale.min = 0;
defaultProps.scale.max = 1;
- defaultProps.scale.type = ScaleTypes.LOG;
+ defaultProps.scale.type = ScaleType.Log;
mount();
expect(setMultipleValidity).toBeCalledWith(Y_EXTENTS, false);
diff --git a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.tsx
similarity index 83%
rename from src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.tsx
index 4e23ee5a41554..11d049d4864a7 100644
--- a/src/plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/y_extents.tsx
@@ -21,15 +21,15 @@ import React, { useEffect, useCallback } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { Scale } from '../../../types';
-import { ScaleTypes } from '../../../utils/collections';
-import { NumberInputOption } from '../../../../../charts/public';
+import { NumberInputOption } from '../../../../../../charts/public';
+
+import { Scale, ScaleType } from '../../../../types';
import { SetScale } from './value_axis_options';
-const rangeError = i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.minErrorMessage', {
+const rangeError = i18n.translate('visTypeXy.controls.pointSeries.valueAxes.minErrorMessage', {
defaultMessage: 'Min should be less than Max.',
});
-const minError = i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.minNeededScaleText', {
+const minError = i18n.translate('visTypeXy.controls.pointSeries.valueAxes.minNeededScaleText', {
defaultMessage: 'Min must exceed 0 when a log scale is selected.',
});
@@ -59,7 +59,7 @@ function YExtents({ scale, setScale, setMultipleValidity }: YExtentsProps) {
errors.push(rangeError);
}
- if (type === ScaleTypes.LOG && (isNullOrUndefined(min) || min <= 0)) {
+ if (type === ScaleType.Log && (isNullOrUndefined(min) || min <= 0)) {
errors.push(minError);
}
@@ -86,7 +86,7 @@ function YExtents({ scale, setScale, setMultipleValidity }: YExtentsProps) {
) {
+ const { stateParams, setValue, vis, aggs } = props;
+
+ const hasLineChart = stateParams.seriesParams.some(
+ ({ type, data: { id: paramId } }) =>
+ (type === ChartType.Line || type === ChartType.Area) &&
+ aggs.aggs.find(({ id }) => id === paramId)?.enabled
+ );
+
+ return (
+ <>
+
+
+ {hasLineChart && (
+
+ )}
+ >
+ );
+}
diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/point_series/grid_panel.tsx
similarity index 59%
rename from src/plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/point_series/grid_panel.tsx
index 0126dce37c9f2..c6ad52f7112c9 100644
--- a/src/plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/point_series/grid_panel.tsx
@@ -16,25 +16,37 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import React, { useMemo, useEffect, useCallback } from 'react';
-import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
+
+import { SelectOption, SwitchOption } from '../../../../../../charts/public';
-import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
-import { SelectOption, SwitchOption } from '../../../../../charts/public';
-import { BasicVislibParams, ValueAxis } from '../../../types';
+import { VisParams, ValueAxis } from '../../../../types';
+import { ValidationVisOptionsProps } from '../../common';
-function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps) {
+type GridPanelOptions = ValidationVisOptionsProps<
+ VisParams,
+ {
+ showElasticChartsOptions: boolean;
+ }
+>;
+
+function GridPanel({ stateParams, setValue, hasHistogramAgg, extraProps }: GridPanelOptions) {
const setGrid = useCallback(
- (
- paramName: T,
- value: BasicVislibParams['grid'][T]
- ) => setValue('grid', { ...stateParams.grid, [paramName]: value }),
+ (paramName: T, value: VisParams['grid'][T]) =>
+ setValue('grid', { ...stateParams.grid, [paramName]: value }),
[stateParams.grid, setValue]
);
+ const disableCategoryGridLines = useMemo(
+ () => !extraProps?.showElasticChartsOptions && hasHistogramAgg,
+ [extraProps?.showElasticChartsOptions, hasHistogramAgg]
+ );
+
const options = useMemo(
() => [
...stateParams.valueAxes.map(({ id, name }: ValueAxis) => ({
@@ -42,7 +54,7 @@ function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps {
- if (hasHistogramAgg) {
+ if (disableCategoryGridLines) {
setGrid('categoryLines', false);
}
- }, [hasHistogramAgg, setGrid]);
+ }, [disableCategoryGridLines, setGrid]);
return (
@@ -71,19 +83,16 @@ function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps
diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/index.ts b/src/plugins/vis_type_xy/public/editor/components/options/point_series/index.ts
similarity index 100%
rename from src/plugins/vis_type_vislib/public/components/options/point_series/index.ts
rename to src/plugins/vis_type_xy/public/editor/components/options/point_series/index.ts
diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx b/src/plugins/vis_type_xy/public/editor/components/options/point_series/point_series.tsx
similarity index 64%
rename from src/plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/point_series/point_series.tsx
index 18073d2218877..283fc28aed46e 100644
--- a/src/plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/point_series/point_series.tsx
@@ -16,25 +16,41 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import React, { useMemo } from 'react';
import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { uniq } from 'lodash';
-import { ValidationVisOptionsProps } from '../../common';
-import { BasicOptions, SwitchOption } from '../../../../../charts/public';
+import { BasicOptions, SwitchOption } from '../../../../../../charts/public';
+import { BUCKET_TYPES } from '../../../../../../data/public';
+
+import { VisParams } from '../../../../types';
import { GridPanel } from './grid_panel';
import { ThresholdPanel } from './threshold_panel';
-import { BasicVislibParams } from '../../../types';
-import { ChartTypes } from '../../../utils/collections';
-
-function PointSeriesOptions(props: ValidationVisOptionsProps) {
- const { stateParams, setValue, vis } = props;
+import { ChartType } from '../../../../../common';
+import { ValidationVisOptionsProps } from '../../common';
+import { ElasticChartsOptions } from './elastic_charts_options';
- const currentChartTypes = useMemo(() => uniq(stateParams.seriesParams.map(({ type }) => type)), [
- stateParams.seriesParams,
- ]);
+export function PointSeriesOptions(
+ props: ValidationVisOptionsProps<
+ VisParams,
+ {
+ // TODO: Remove when vis_type_vislib is removed
+ // https://github.com/elastic/kibana/issues/56143
+ showElasticChartsOptions: boolean;
+ }
+ >
+) {
+ const { stateParams, setValue, vis, aggs } = props;
+ const hasBarChart = useMemo(
+ () =>
+ stateParams.seriesParams.some(
+ ({ type, data: { id: paramId } }) =>
+ type === ChartType.Histogram && aggs.aggs.find(({ id }) => id === paramId)?.enabled
+ ),
+ [stateParams.seriesParams, aggs.aggs]
+ );
return (
<>
@@ -42,7 +58,7 @@ function PointSeriesOptions(props: ValidationVisOptionsProps)
@@ -52,10 +68,11 @@ function PointSeriesOptions(props: ValidationVisOptionsProps)
{vis.data.aggs!.aggs.some(
- (agg) => agg.schema === 'segment' && agg.type.name === 'date_histogram'
+ (agg) => agg.schema === 'segment' && agg.type.name === BUCKET_TYPES.DATE_HISTOGRAM
) ? (
)
/>
) : (
)
/>
)}
- {currentChartTypes.includes(ChartTypes.HISTOGRAM) && (
+ {hasBarChart && (
)
}
/>
)}
+
+ {props.extraProps?.showElasticChartsOptions && }
@@ -98,5 +118,3 @@ function PointSeriesOptions(props: ValidationVisOptionsProps)
>
);
}
-
-export { PointSeriesOptions };
diff --git a/src/plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/point_series/threshold_panel.tsx
similarity index 77%
rename from src/plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx
rename to src/plugins/vis_type_xy/public/editor/components/options/point_series/threshold_panel.tsx
index 964bb7d569b08..ec21a386a5679 100644
--- a/src/plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx
+++ b/src/plugins/vis_type_xy/public/editor/components/options/point_series/threshold_panel.tsx
@@ -17,39 +17,41 @@
* under the License.
*/
import React, { useCallback } from 'react';
-import { EuiPanel, EuiTitle, EuiColorPicker, EuiFormRow, EuiSpacer } from '@elastic/eui';
+
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiPanel, EuiTitle, EuiColorPicker, EuiFormRow, EuiSpacer } from '@elastic/eui';
-import { ValidationVisOptionsProps } from '../../common';
import {
SelectOption,
SwitchOption,
RequiredNumberInputOption,
-} from '../../../../../charts/public';
-import { BasicVislibParams } from '../../../types';
+} from '../../../../../../charts/public';
+
+import { ValidationVisOptionsProps } from '../../common';
+import { VisParams } from '../../../../types';
function ThresholdPanel({
stateParams,
setValue,
setMultipleValidity,
vis,
-}: ValidationVisOptionsProps) {
+}: ValidationVisOptionsProps) {
const setThresholdLine = useCallback(
- (
+ (
paramName: T,
- value: BasicVislibParams['thresholdLine'][T]
+ value: VisParams['thresholdLine'][T]
) => setValue('thresholdLine', { ...stateParams.thresholdLine, [paramName]: value }),
[stateParams.thresholdLine, setValue]
);
const setThresholdLineColor = useCallback(
- (value: BasicVislibParams['thresholdLine']['color']) => setThresholdLine('color', value),
+ (value: VisParams['thresholdLine']['color']) => setThresholdLine('color', value),
[setThresholdLine]
);
const setThresholdLineValidity = useCallback(
- (paramName: keyof BasicVislibParams['thresholdLine'], isValid: boolean) =>
+ (paramName: keyof VisParams['thresholdLine'], isValid: boolean) =>
setMultipleValidity(`thresholdLine__${paramName}`, isValid),
[setMultipleValidity]
);
@@ -59,7 +61,7 @@ function ThresholdPanel({
@@ -67,7 +69,7 @@ function ThresholdPanel({
import('./components/data_view'));
+import { i18n } from '@kbn/i18n';
+import { Position } from '@elastic/charts';
-export const getDataViewDescription = (): InspectorViewDescription => ({
- title: i18n.translate('inspector.data.dataTitle', {
- defaultMessage: 'Data',
- }),
- order: 10,
- help: i18n.translate('inspector.data.dataDescriptionTooltip', {
- defaultMessage: 'View the data behind the visualization',
- }),
- shouldShow(adapters: Adapters) {
- return Boolean(adapters.data);
+export const getPositions = () => [
+ {
+ text: i18n.translate('visTypeXy.legendPositions.topText', {
+ defaultMessage: 'Top',
+ }),
+ value: Position.Top,
+ },
+ {
+ text: i18n.translate('visTypeXy.legendPositions.leftText', {
+ defaultMessage: 'Left',
+ }),
+ value: Position.Left,
+ },
+ {
+ text: i18n.translate('visTypeXy.legendPositions.rightText', {
+ defaultMessage: 'Right',
+ }),
+ value: Position.Right,
+ },
+ {
+ text: i18n.translate('visTypeXy.legendPositions.bottomText', {
+ defaultMessage: 'Bottom',
+ }),
+ value: Position.Bottom,
},
- component: DataViewComponent,
-});
+];
diff --git a/src/plugins/ui_actions/public/triggers/select_range_trigger.ts b/src/plugins/vis_type_xy/public/editor/scale_types.ts
similarity index 62%
rename from src/plugins/ui_actions/public/triggers/select_range_trigger.ts
rename to src/plugins/vis_type_xy/public/editor/scale_types.ts
index 312e75314bd92..c115b04ead5fd 100644
--- a/src/plugins/ui_actions/public/triggers/select_range_trigger.ts
+++ b/src/plugins/vis_type_xy/public/editor/scale_types.ts
@@ -18,15 +18,26 @@
*/
import { i18n } from '@kbn/i18n';
-import { Trigger } from '.';
-export const SELECT_RANGE_TRIGGER = 'SELECT_RANGE_TRIGGER';
-export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> = {
- id: SELECT_RANGE_TRIGGER,
- title: i18n.translate('uiActions.triggers.selectRangeTitle', {
- defaultMessage: 'Range selection',
- }),
- description: i18n.translate('uiActions.triggers.selectRangeDescription', {
- defaultMessage: 'A range of values on the visualization',
- }),
-};
+import { ScaleType } from '../types';
+
+export const getScaleTypes = () => [
+ {
+ text: i18n.translate('visTypeXy.scaleTypes.linearText', {
+ defaultMessage: 'Linear',
+ }),
+ value: ScaleType.Linear,
+ },
+ {
+ text: i18n.translate('visTypeXy.scaleTypes.logText', {
+ defaultMessage: 'Log',
+ }),
+ value: ScaleType.Log,
+ },
+ {
+ text: i18n.translate('visTypeXy.scaleTypes.squareRootText', {
+ defaultMessage: 'Square root',
+ }),
+ value: ScaleType.SquareRoot,
+ },
+];
diff --git a/src/plugins/vis_type_xy/public/index.ts b/src/plugins/vis_type_xy/public/index.ts
index 9af75ce9059e9..0739ad77a245b 100644
--- a/src/plugins/vis_type_xy/public/index.ts
+++ b/src/plugins/vis_type_xy/public/index.ts
@@ -17,11 +17,35 @@
* under the License.
*/
-import { PluginInitializerContext } from '../../../core/public';
import { VisTypeXyPlugin as Plugin } from './plugin';
export { VisTypeXyPluginSetup } from './plugin';
-export function plugin(initializerContext: PluginInitializerContext) {
- return new Plugin(initializerContext);
+// TODO: Remove when vis_type_vislib is removed
+// https://github.com/elastic/kibana/issues/56143
+export {
+ CategoryAxis,
+ ThresholdLine,
+ ValueAxis,
+ Grid,
+ SeriesParam,
+ Dimension,
+ Dimensions,
+ ScaleType,
+ AxisType,
+ HistogramParams,
+ DateHistogramParams,
+} from './types';
+export type { ValidationVisOptionsProps } from './editor/components/common/validation_wrapper';
+export { TruncateLabelsOption } from './editor/components/common/truncate_labels';
+export { getPositions } from './editor/positions';
+export { getScaleTypes } from './editor/scale_types';
+export { xyVisTypes } from './vis_types';
+export { getAggId } from './config/get_agg_id';
+
+// Export common types
+export * from '../common';
+
+export function plugin() {
+ return new Plugin();
}
diff --git a/src/plugins/vis_type_xy/public/plugin.ts b/src/plugins/vis_type_xy/public/plugin.ts
index 667018c1e6e30..7425c5f7248ac 100644
--- a/src/plugins/vis_type_xy/public/plugin.ts
+++ b/src/plugins/vis_type_xy/public/plugin.ts
@@ -17,25 +17,30 @@
* under the License.
*/
-import {
- CoreSetup,
- CoreStart,
- Plugin,
- IUiSettingsClient,
- PluginInitializerContext,
-} from 'kibana/public';
-
+import { CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public';
import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/public';
import { ChartsPluginSetup } from '../../charts/public';
+import { DataPublicPluginStart } from '../../data/public';
-export interface VisTypeXyDependencies {
- uiSettings: IUiSettingsClient;
- charts: ChartsPluginSetup;
-}
+import { createVisTypeXyVisFn } from './xy_vis_fn';
+import {
+ setDataActions,
+ setFormatService,
+ setThemeService,
+ setColorsService,
+ setTimefilter,
+ setUISettings,
+ setDocLinks,
+} from './services';
+import { visTypesDefinitions } from './vis_types';
+import { LEGACY_CHARTS_LIBRARY } from '../common';
+import { xyVisRenderer } from './vis_renderer';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface VisTypeXyPluginSetup {}
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+export interface VisTypeXyPluginStart {}
/** @internal */
export interface VisTypeXyPluginSetupDependencies {
@@ -48,40 +53,43 @@ export interface VisTypeXyPluginSetupDependencies {
export interface VisTypeXyPluginStartDependencies {
expressions: ReturnType;
visualizations: VisualizationsStart;
+ data: DataPublicPluginStart;
}
-type VisTypeXyCoreSetup = CoreSetup;
+type VisTypeXyCoreSetup = CoreSetup;
/** @internal */
-export class VisTypeXyPlugin implements Plugin {
- constructor(public initializerContext: PluginInitializerContext) {}
-
+export class VisTypeXyPlugin
+ implements
+ Plugin<
+ VisTypeXyPluginSetup,
+ VisTypeXyPluginStart,
+ VisTypeXyPluginSetupDependencies,
+ VisTypeXyPluginStartDependencies
+ > {
public async setup(
core: VisTypeXyCoreSetup,
{ expressions, visualizations, charts }: VisTypeXyPluginSetupDependencies
) {
- // eslint-disable-next-line no-console
- console.warn(
- 'The visTypeXy plugin is enabled\n\n',
- 'This may negatively alter existing vislib visualization configurations if saved.'
- );
- const visualizationDependencies: Readonly = {
- uiSettings: core.uiSettings,
- charts,
- };
-
- const visTypeDefinitions: any[] = [];
- const visFunctions: any = [];
+ if (!core.uiSettings.get(LEGACY_CHARTS_LIBRARY, true)) {
+ setUISettings(core.uiSettings);
+ setThemeService(charts.theme);
+ setColorsService(charts.legacyColors);
- visFunctions.forEach((fn: any) => expressions.registerFunction(fn));
- visTypeDefinitions.forEach((vis: any) =>
- visualizations.createBaseVisualization(vis(visualizationDependencies))
- );
+ [createVisTypeXyVisFn].forEach(expressions.registerFunction);
+ expressions.registerRenderer(xyVisRenderer);
+ visTypesDefinitions.forEach(visualizations.createBaseVisualization);
+ }
return {};
}
- public start(core: CoreStart, deps: VisTypeXyPluginStartDependencies) {
- // nothing to do here
+ public start(core: CoreStart, { data }: VisTypeXyPluginStartDependencies) {
+ setFormatService(data.fieldFormats);
+ setDataActions(data.actions);
+ setTimefilter(data.query.timefilter.timefilter);
+ setDocLinks(core.docLinks);
+
+ return {};
}
}
diff --git a/src/plugins/vis_type_xy/public/services.ts b/src/plugins/vis_type_xy/public/services.ts
new file mode 100644
index 0000000000000..5a72759ecff6c
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/services.ts
@@ -0,0 +1,49 @@
+/*
+ * 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, DocLinksStart } from '../../../core/public';
+import { createGetterSetter } from '../../kibana_utils/public';
+import { DataPublicPluginStart } from '../../data/public';
+import { ChartsPluginSetup } from '../../charts/public';
+
+export const [getUISettings, setUISettings] = createGetterSetter(
+ 'xy core.uiSettings'
+);
+
+export const [getDataActions, setDataActions] = createGetterSetter<
+ DataPublicPluginStart['actions']
+>('xy data.actions');
+
+export const [getFormatService, setFormatService] = createGetterSetter<
+ DataPublicPluginStart['fieldFormats']
+>('xy data.fieldFormats');
+
+export const [getTimefilter, setTimefilter] = createGetterSetter<
+ DataPublicPluginStart['query']['timefilter']['timefilter']
+>('xy data.query.timefilter.timefilter');
+
+export const [getThemeService, setThemeService] = createGetterSetter(
+ 'xy charts.theme'
+);
+
+export const [getColorsService, setColorsService] = createGetterSetter<
+ ChartsPluginSetup['legacyColors']
+>('xy charts.color');
+
+export const [getDocLinks, setDocLinks] = createGetterSetter('DocLinks');
diff --git a/src/plugins/vis_type_xy/public/to_ast.test.ts b/src/plugins/vis_type_xy/public/to_ast.test.ts
new file mode 100644
index 0000000000000..678a9faaec585
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/to_ast.test.ts
@@ -0,0 +1,60 @@
+/*
+ * 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 { Vis } from '../../visualizations/public';
+import { buildExpression } from '../../expressions/public';
+import { sampleAreaVis } from '../../vis_type_vislib/public/sample_vis.test.mocks';
+
+import { toExpressionAst } from './to_ast';
+import { VisParams } from './types';
+
+jest.mock('../../expressions/public', () => ({
+ ...(jest.requireActual('../../expressions/public') as any),
+ buildExpression: jest.fn().mockImplementation(() => ({
+ toAst: () => ({
+ type: 'expression',
+ chain: [],
+ }),
+ })),
+}));
+
+jest.mock('./to_ast_esaggs', () => ({
+ getEsaggsFn: jest.fn(),
+}));
+
+describe('xy vis toExpressionAst function', () => {
+ let vis: Vis;
+
+ const params = {
+ timefilter: {},
+ timeRange: {},
+ abortSignal: {},
+ } as any;
+
+ beforeEach(() => {
+ vis = sampleAreaVis as any;
+ });
+
+ it('should match basic snapshot', () => {
+ toExpressionAst(vis, params);
+ const [, builtExpression] = (buildExpression as jest.Mock).mock.calls[0][0];
+
+ expect(builtExpression).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/vis_type_xy/public/to_ast.ts b/src/plugins/vis_type_xy/public/to_ast.ts
new file mode 100644
index 0000000000000..c93dbe46dca0e
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/to_ast.ts
@@ -0,0 +1,94 @@
+/*
+ * 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 moment from 'moment';
+
+import { VisToExpressionAst, getVisSchemas } from '../../visualizations/public';
+import { buildExpression, buildExpressionFunction } from '../../expressions/public';
+import { BUCKET_TYPES } from '../../data/public';
+
+import { DateHistogramParams, Dimensions, HistogramParams, VisParams } from './types';
+import { visName, VisTypeXyExpressionFunctionDefinition } from './xy_vis_fn';
+import { XyVisType } from '../common';
+import { getEsaggsFn } from './to_ast_esaggs';
+
+export const toExpressionAst: VisToExpressionAst = async (vis, params) => {
+ const schemas = getVisSchemas(vis, params);
+ const dimensions: Dimensions = {
+ x: schemas.segment ? schemas.segment[0] : null,
+ y: schemas.metric,
+ z: schemas.radius,
+ width: schemas.width,
+ series: schemas.group,
+ splitRow: schemas.split_row,
+ splitColumn: schemas.split_column,
+ };
+
+ const responseAggs = vis.data.aggs?.getResponseAggs().filter(({ enabled }) => enabled) ?? [];
+
+ if (dimensions.x) {
+ const xAgg = responseAggs[dimensions.x.accessor] as any;
+ if (xAgg.type.name === BUCKET_TYPES.DATE_HISTOGRAM) {
+ (dimensions.x.params as DateHistogramParams).date = true;
+ const { esUnit, esValue } = xAgg.buckets.getInterval();
+ (dimensions.x.params as DateHistogramParams).intervalESUnit = esUnit;
+ (dimensions.x.params as DateHistogramParams).intervalESValue = esValue;
+ (dimensions.x.params as DateHistogramParams).interval = moment
+ .duration(esValue, esUnit)
+ .asMilliseconds();
+ (dimensions.x.params as DateHistogramParams).format = xAgg.buckets.getScaledDateFormat();
+ } else if (xAgg.type.name === BUCKET_TYPES.HISTOGRAM) {
+ const intervalParam = xAgg.type.paramByName('interval');
+ const output = { params: {} as any };
+ await intervalParam.modifyAggConfigOnSearchRequestStart(xAgg, vis.data.searchSource, {
+ abortSignal: params.abortSignal,
+ });
+ intervalParam.write(xAgg, output);
+ (dimensions.x.params as HistogramParams).interval = output.params.interval;
+ }
+ }
+
+ const visConfig = { ...vis.params };
+
+ (dimensions.y || []).forEach((yDimension) => {
+ const yAgg = responseAggs[yDimension.accessor];
+ const seriesParam = (visConfig.seriesParams || []).find(
+ (param: any) => param.data.id === yAgg.id
+ );
+ if (seriesParam) {
+ const usedValueAxis = (visConfig.valueAxes || []).find(
+ (valueAxis: any) => valueAxis.id === seriesParam.valueAxis
+ );
+ if (usedValueAxis?.scale.mode === 'percentage') {
+ yDimension.format = { id: 'percent' };
+ }
+ }
+ });
+
+ visConfig.dimensions = dimensions;
+
+ const visTypeXy = buildExpressionFunction(visName, {
+ type: vis.type.name as XyVisType,
+ visConfig: JSON.stringify(visConfig),
+ });
+
+ const ast = buildExpression([getEsaggsFn(vis), visTypeXy]);
+
+ return ast.toAst();
+};
diff --git a/src/plugins/vis_type_xy/public/to_ast_esaggs.ts b/src/plugins/vis_type_xy/public/to_ast_esaggs.ts
new file mode 100644
index 0000000000000..da8d11ac8340c
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/to_ast_esaggs.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 { Vis } from '../../visualizations/public';
+import { buildExpression, buildExpressionFunction } from '../../expressions/public';
+import {
+ EsaggsExpressionFunctionDefinition,
+ IndexPatternLoadExpressionFunctionDefinition,
+} from '../../data/public';
+
+import { VisParams } from './types';
+
+/**
+ * Get esaggs expressions function
+ * TODO: replace this with vis.data.aggs!.toExpressionAst();
+ * https://github.com/elastic/kibana/issues/61768
+ * @param vis
+ */
+export function getEsaggsFn(vis: Vis) {
+ return buildExpressionFunction('esaggs', {
+ index: buildExpression([
+ buildExpressionFunction('indexPatternLoad', {
+ id: vis.data.indexPattern!.id!,
+ }),
+ ]),
+ metricsAtAllLevels: vis.isHierarchical(),
+ partialRows: false,
+ aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())),
+ });
+}
diff --git a/src/plugins/vis_type_xy/public/types/config.ts b/src/plugins/vis_type_xy/public/types/config.ts
new file mode 100644
index 0000000000000..ec73c0f6e3fc0
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/types/config.ts
@@ -0,0 +1,130 @@
+/*
+ * 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 {
+ AxisSpec,
+ CustomTooltip,
+ Fit,
+ GridLineStyle,
+ Position,
+ Rotation,
+ SeriesScales,
+ TickFormatter,
+ TooltipProps,
+ TooltipValueFormatter,
+ YDomainRange,
+} from '@elastic/charts';
+
+import { Dimension, Scale, ThresholdLine } from './param';
+
+export interface Column {
+ id: string | null;
+ name: string;
+}
+
+export interface Aspect {
+ accessor: Column['id'];
+ aggType: string | null;
+ aggId: string | null;
+ column?: Dimension['accessor'];
+ title: Column['name'];
+ format?: Dimension['format'];
+ formatter?: TickFormatter;
+ params: Dimension['params'];
+}
+
+export interface Aspects {
+ x: Aspect;
+ y: Aspect[];
+ z?: Aspect;
+ series?: Aspect[];
+}
+
+export interface AxisGrid {
+ show?: boolean;
+ styles?: GridLineStyle;
+}
+
+export interface TickOptions {
+ show?: boolean;
+ size?: number;
+ count?: number;
+ padding?: number;
+ formatter?: TickFormatter;
+ labelFormatter?: TickFormatter;
+ rotation?: number;
+ showDuplicates?: boolean;
+ integersOnly?: boolean;
+ showOverlappingTicks?: boolean;
+ showOverlappingLabels?: boolean;
+}
+
+export type YScaleType = SeriesScales['yScaleType'];
+export type XScaleType = SeriesScales['xScaleType'];
+
+export type ScaleConfig = Omit & {
+ type?: S;
+};
+
+export interface AxisConfig {
+ id: string;
+ groupId?: string;
+ position: Position;
+ ticks?: TickOptions;
+ show: boolean;
+ style: AxisSpec['style'];
+ scale: ScaleConfig;
+ domain?: YDomainRange;
+ title?: string;
+ grid?: AxisGrid;
+ integersOnly: boolean;
+}
+
+export interface LegendOptions {
+ show: boolean;
+ position?: Position;
+}
+
+export type ThresholdLineConfig = Omit & {
+ dash?: number[];
+ groupId?: string;
+};
+
+export type TooltipConfig = Omit & {
+ detailedTooltip?: (headerFormatter?: TooltipValueFormatter) => CustomTooltip;
+};
+
+export interface VisConfig {
+ legend: LegendOptions;
+ tooltip: TooltipConfig;
+ xAxis: AxisConfig;
+ yAxes: Array>;
+ aspects: Aspects;
+ rotation: Rotation;
+ thresholdLine: ThresholdLineConfig;
+ orderBucketsBySum?: boolean;
+ showCurrentTime: boolean;
+ isTimeChart: boolean;
+ markSizeRatio: number;
+ showValueLabel: boolean;
+ enableHistogramMode: boolean;
+ fittingFunction?: Exclude;
+ detailedTooltip?: boolean;
+ isVislibVis?: boolean;
+}
diff --git a/src/plugins/vis_type_xy/public/types/constants.ts b/src/plugins/vis_type_xy/public/types/constants.ts
new file mode 100644
index 0000000000000..f92c56e43413e
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/types/constants.ts
@@ -0,0 +1,67 @@
+/*
+ * 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 { $Values } from '@kbn/utility-types';
+
+export const ChartMode = Object.freeze({
+ Normal: 'normal' as const,
+ Stacked: 'stacked' as const,
+});
+export type ChartMode = $Values;
+
+export const InterpolationMode = Object.freeze({
+ Linear: 'linear' as const,
+ Cardinal: 'cardinal' as const,
+ StepAfter: 'step-after' as const,
+});
+export type InterpolationMode = $Values;
+
+export const AxisType = Object.freeze({
+ Category: 'category' as const,
+ Value: 'value' as const,
+});
+export type AxisType = $Values;
+
+export const ScaleType = Object.freeze({
+ Linear: 'linear' as const,
+ Log: 'log' as const,
+ SquareRoot: 'square root' as const,
+});
+export type ScaleType = $Values;
+
+export const AxisMode = Object.freeze({
+ Normal: 'normal' as const,
+ Percentage: 'percentage' as const,
+ Wiggle: 'wiggle' as const,
+ Silhouette: 'silhouette' as const,
+});
+export type AxisMode = $Values;
+
+export const ThresholdLineStyle = Object.freeze({
+ Full: 'full' as const,
+ Dashed: 'dashed' as const,
+ DotDashed: 'dot-dashed' as const,
+});
+export type ThresholdLineStyle = $Values;
+
+export const ColorMode = Object.freeze({
+ Background: 'Background' as const,
+ Labels: 'Labels' as const,
+ None: 'None' as const,
+});
+export type ColorMode = $Values;
diff --git a/src/plugins/vis_type_xy/public/types/index.ts b/src/plugins/vis_type_xy/public/types/index.ts
new file mode 100644
index 0000000000000..791373def2018
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/types/index.ts
@@ -0,0 +1,23 @@
+/*
+ * 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 * from './constants';
+export * from './config';
+export * from './param';
+export * from './vis_type';
diff --git a/src/plugins/vis_type_xy/public/types/param.ts b/src/plugins/vis_type_xy/public/types/param.ts
new file mode 100644
index 0000000000000..c8cd020dec03c
--- /dev/null
+++ b/src/plugins/vis_type_xy/public/types/param.ts
@@ -0,0 +1,160 @@
+/*
+ * 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 { Fit, Position } from '@elastic/charts';
+
+import { Style, Labels } from '../../../charts/public';
+import { SchemaConfig } from '../../../visualizations/public';
+
+import { ChartType } from '../../common';
+import {
+ ChartMode,
+ AxisMode,
+ AxisType,
+ InterpolationMode,
+ ScaleType,
+ ThresholdLineStyle,
+} from './constants';
+
+export interface Scale {
+ boundsMargin?: number | '';
+ defaultYExtents?: boolean;
+ max?: number | null;
+ min?: number | null;
+ mode?: AxisMode;
+ setYExtents?: boolean;
+ type: ScaleType;
+}
+
+export interface CategoryAxis {
+ id: string;
+ labels: Labels;
+ position: Position;
+ scale: Scale;
+ show: boolean;
+ title: {
+ text?: string;
+ };
+ type: AxisType;
+ /**
+ * Used only for heatmap, here for consistent types when used in vis_type_vislib
+ *
+ * remove with vis_type_vislib
+ * https://github.com/elastic/kibana/issues/56143
+ */
+ style: Partial