Add imperative delete field api (#93181) (#94310)

This commit is contained in:
Joe Reuter 2021-03-10 18:42:43 +01:00 committed by GitHub
parent 7c9077fdc5
commit 34a7dae336
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 496 additions and 216 deletions

View file

@ -253,6 +253,70 @@
},
"initialIsOpen": false
},
{
"id": "def-public.OpenFieldDeleteModalOptions",
"type": "Interface",
"label": "OpenFieldDeleteModalOptions",
"description": [],
"tags": [],
"children": [
{
"tags": [],
"id": "def-public.OpenFieldDeleteModalOptions.ctx",
"type": "Object",
"label": "ctx",
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/open_delete_modal.tsx",
"lineNumber": 25
},
"signature": [
"{ indexPattern: ",
{
"pluginId": "data",
"scope": "common",
"docId": "kibDataIndexPatternsPluginApi",
"section": "def-common.IndexPattern",
"text": "IndexPattern"
},
"; }"
]
},
{
"tags": [],
"id": "def-public.OpenFieldDeleteModalOptions.onDelete",
"type": "Function",
"label": "onDelete",
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/open_delete_modal.tsx",
"lineNumber": 28
},
"signature": [
"((fieldNames: string[]) => void) | undefined"
]
},
{
"tags": [],
"id": "def-public.OpenFieldDeleteModalOptions.fieldName",
"type": "CompoundType",
"label": "fieldName",
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/open_delete_modal.tsx",
"lineNumber": 29
},
"signature": [
"string | string[]"
]
}
],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/open_delete_modal.tsx",
"lineNumber": 24
},
"initialIsOpen": false
},
{
"id": "def-public.OpenFieldEditorOptions",
"type": "Interface",
@ -369,7 +433,7 @@
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 26
"lineNumber": 27
}
}
],
@ -377,7 +441,51 @@
"returnComment": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 26
"lineNumber": 27
}
},
{
"id": "def-public.PluginStart.openDeleteModal",
"type": "Function",
"label": "openDeleteModal",
"signature": [
"(options: ",
{
"pluginId": "indexPatternFieldEditor",
"scope": "public",
"docId": "kibIndexPatternFieldEditorPluginApi",
"section": "def-public.OpenFieldDeleteModalOptions",
"text": "OpenFieldDeleteModalOptions"
},
") => () => void"
],
"description": [],
"children": [
{
"type": "Object",
"label": "options",
"isRequired": true,
"signature": [
{
"pluginId": "indexPatternFieldEditor",
"scope": "public",
"docId": "kibIndexPatternFieldEditorPluginApi",
"section": "def-public.OpenFieldDeleteModalOptions",
"text": "OpenFieldDeleteModalOptions"
}
],
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 28
}
}
],
"tags": [],
"returnComment": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 28
}
},
{
@ -388,7 +496,7 @@
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 27
"lineNumber": 29
},
"signature": [
"{ getAll: () => typeof ",
@ -418,7 +526,7 @@
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 28
"lineNumber": 30
},
"signature": [
"{ editIndexPattern: () => boolean; }"
@ -432,7 +540,7 @@
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 31
"lineNumber": 33
},
"signature": [
"React.FunctionComponent<",
@ -449,7 +557,7 @@
],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 25
"lineNumber": 26
},
"lifecycle": "start",
"initialIsOpen": true

View file

@ -13,6 +13,10 @@ You first need to add in your kibana.json the "`indexPatternFieldEditor`" plugin
You will then receive in the start contract of the indexPatternFieldEditor plugin the following API:
### `userPermissions.editIndexPattern(): boolean`
Convenience method that uses the `core.application.capabilities` api to determine whether the user can edit the index pattern.
### `openEditor(options: OpenFieldEditorOptions): CloseEditor`
Use this method to open the index pattern field editor to either create (runtime) or edit (concrete | runtime) a field.
@ -33,13 +37,29 @@ You can provide an optional `onSave` handler to be notified when the field has b
You can optionally pass the name of a field to edit. Leave empty to create a new runtime field based field.
### `userPermissions.editIndexPattern(): boolean`
### `openDeleteModal(options: OpenFieldDeleteModalOptions): CloseEditor`
Convenience method that uses the `core.application.capabilities` api to determine whether the user can edit the index pattern.
Use this method to open a confirmation modal to delete runtime fields from an index pattern.
#### `options`
`ctx: FieldEditorContext` (**required**)
You need to provide the context in which the deletion modal is being consumed. This object has the following properties:
- `indexPattern: IndexPattern`: the index pattern you want to delete fields from.
`onDelete(fieldNames: string[]): void` (optional)
You can provide an optional `onDelete` handler to be notified when the fields have been deleted. This handler is called after the deletion has been persisted to the saved object.
`fieldName: string | string[]` (**required**)
You have to pass the field or fields to delete.
### `<DeleteRuntimeFieldProvider />`
This children func React component provides a handler to delete one or multiple runtime fields.
This children func React component provides a handler to delete one or multiple runtime fields. It can be used as an alternative to `openDeleteModal` in a react context.
#### Props

View file

@ -0,0 +1,90 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiConfirmModal } from '@elastic/eui';
const geti18nTexts = (fieldsToDelete?: string[]) => {
let modalTitle = '';
if (fieldsToDelete) {
const isSingle = fieldsToDelete.length === 1;
modalTitle = isSingle
? i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmModal.deleteSingleTitle',
{
defaultMessage: `Remove field '{name}'?`,
values: { name: fieldsToDelete[0] },
}
)
: i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmModal.deleteMultipleTitle',
{
defaultMessage: `Remove {count} fields?`,
values: { count: fieldsToDelete.length },
}
);
}
return {
modalTitle,
confirmButtonText: i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmationModal.removeButtonLabel',
{
defaultMessage: 'Remove',
}
),
cancelButtonText: i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmationModal.cancelButtonLabel',
{
defaultMessage: 'Cancel',
}
),
warningMultipleFields: i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmModal.multipleDeletionDescription',
{
defaultMessage: 'You are about to remove these runtime fields:',
}
),
};
};
export interface Props {
fieldsToDelete: string[];
closeModal: () => void;
confirmDelete: () => void;
}
export function DeleteFieldModal({ fieldsToDelete, closeModal, confirmDelete }: Props) {
const i18nTexts = geti18nTexts(fieldsToDelete);
const { modalTitle, confirmButtonText, cancelButtonText, warningMultipleFields } = i18nTexts;
const isMultiple = Boolean(fieldsToDelete.length > 1);
return (
<EuiConfirmModal
title={modalTitle}
data-test-subj="runtimeFieldDeleteConfirmModal"
onCancel={closeModal}
onConfirm={confirmDelete}
cancelButtonText={cancelButtonText}
buttonColor="danger"
confirmButtonText={confirmButtonText}
>
{isMultiple && (
<>
<p>{warningMultipleFields}</p>
<ul>
{fieldsToDelete.map((fieldName) => (
<li key={fieldName}>{fieldName}</li>
))}
</ul>
</>
)}
</EuiConfirmModal>
);
}

View file

@ -0,0 +1,53 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { useCallback, useRef, useEffect } from 'react';
import { IndexPattern } from '../shared_imports';
import { OpenFieldDeleteModalOptions } from '../open_delete_modal';
import { CloseEditor } from '../types';
type DeleteFieldFunc = (fieldName: string | string[]) => void;
export interface Props {
children: (deleteFieldHandler: DeleteFieldFunc) => React.ReactNode;
indexPattern: IndexPattern;
onDelete?: (fieldNames: string[]) => void;
}
export const getDeleteFieldProvider = (
modalOpener: (options: OpenFieldDeleteModalOptions) => CloseEditor
): React.FunctionComponent<Props> => {
return React.memo(({ indexPattern, children, onDelete }: Props) => {
const closeModal = useRef<CloseEditor | null>(null);
const deleteFields = useCallback(
async (fieldName: string | string[]) => {
if (closeModal.current) {
closeModal.current();
}
closeModal.current = modalOpener({
ctx: {
indexPattern,
},
fieldName,
onDelete,
});
},
[onDelete, indexPattern]
);
useEffect(() => {
return () => {
if (closeModal.current) {
closeModal.current();
}
};
}, []);
return <>{children(deleteFields)}</>;
});
};

View file

@ -1,129 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { useState, useCallback } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui';
type DeleteFieldFunc = (fieldName: string | string[]) => void;
export interface Props {
children: (deleteFieldHandler: DeleteFieldFunc) => React.ReactNode;
onConfirmDelete: (fieldsToDelete: string[]) => Promise<void>;
}
interface State {
isModalOpen: boolean;
fieldsToDelete: string[];
}
const geti18nTexts = (fieldsToDelete?: string[]) => {
let modalTitle = '';
if (fieldsToDelete) {
const isSingle = fieldsToDelete.length === 1;
modalTitle = isSingle
? i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmModal.deleteSingleTitle',
{
defaultMessage: `Remove field '{name}'?`,
values: { name: fieldsToDelete[0] },
}
)
: i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmModal.deleteMultipleTitle',
{
defaultMessage: `Remove {count} fields?`,
values: { count: fieldsToDelete.length },
}
);
}
return {
modalTitle,
confirmButtonText: i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmationModal.removeButtonLabel',
{
defaultMessage: 'Remove',
}
),
cancelButtonText: i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmationModal.cancelButtonLabel',
{
defaultMessage: 'Cancel',
}
),
warningMultipleFields: i18n.translate(
'indexPatternFieldEditor.deleteRuntimeField.confirmModal.multipleDeletionDescription',
{
defaultMessage: 'You are about to remove these runtime fields:',
}
),
};
};
export const DeleteRuntimeFieldProvider = ({ children, onConfirmDelete }: Props) => {
const [state, setState] = useState<State>({ isModalOpen: false, fieldsToDelete: [] });
const { isModalOpen, fieldsToDelete } = state;
const i18nTexts = geti18nTexts(fieldsToDelete);
const { modalTitle, confirmButtonText, cancelButtonText, warningMultipleFields } = i18nTexts;
const isMultiple = Boolean(fieldsToDelete.length > 1);
const deleteField: DeleteFieldFunc = useCallback((fieldNames) => {
setState({
isModalOpen: true,
fieldsToDelete: Array.isArray(fieldNames) ? fieldNames : [fieldNames],
});
}, []);
const closeModal = useCallback(() => {
setState({ isModalOpen: false, fieldsToDelete: [] });
}, []);
const confirmDelete = useCallback(async () => {
try {
await onConfirmDelete(fieldsToDelete);
closeModal();
} catch (e) {
// silently fail as "onConfirmDelete" is responsible
// to show a toast message if there is an error
}
}, [closeModal, onConfirmDelete, fieldsToDelete]);
return (
<>
{children(deleteField)}
{isModalOpen && (
<EuiOverlayMask>
<EuiConfirmModal
title={modalTitle}
data-test-subj="runtimeFieldDeleteConfirmModal"
onCancel={closeModal}
onConfirm={confirmDelete}
cancelButtonText={cancelButtonText}
buttonColor="danger"
confirmButtonText={confirmButtonText}
>
{isMultiple && (
<>
<p>{warningMultipleFields}</p>
<ul>
{fieldsToDelete.map((fieldName) => (
<li key={fieldName}>{fieldName}</li>
))}
</ul>
</>
)}
</EuiConfirmModal>
</EuiOverlayMask>
)}
</>
);
};

View file

@ -1,59 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { useCallback } from 'react';
import { i18n } from '@kbn/i18n';
import { METRIC_TYPE } from '@kbn/analytics';
import { NotificationsStart } from 'src/core/public';
import { IndexPattern, UsageCollectionStart } from '../../shared_imports';
import { pluginName } from '../../constants';
import { DeleteRuntimeFieldProvider, Props as DeleteProviderProps } from './delete_field_provider';
import { DataPublicPluginStart } from '../../../../data/public';
export interface Props extends Omit<DeleteProviderProps, 'onConfirmDelete'> {
indexPattern: IndexPattern;
onDelete?: (fieldNames: string[]) => void;
}
export const getDeleteProvider = (
indexPatternService: DataPublicPluginStart['indexPatterns'],
usageCollection: UsageCollectionStart,
notifications: NotificationsStart
): React.FunctionComponent<Props> => {
return React.memo(({ indexPattern, children, onDelete }: Props) => {
const deleteFields = useCallback(
async (fieldNames: string[]) => {
fieldNames.forEach((fieldName) => {
indexPattern.removeRuntimeField(fieldName);
});
try {
usageCollection.reportUiCounter(pluginName, METRIC_TYPE.COUNT, 'delete_runtime');
// eslint-disable-next-line no-empty
} catch {}
try {
await indexPatternService.updateSavedObject(indexPattern);
} catch (e) {
const title = i18n.translate('indexPatternFieldEditor.save.deleteErrorTitle', {
defaultMessage: 'Failed to save field removal',
});
notifications.toasts.addError(e, { title });
}
if (onDelete) {
onDelete(fieldNames);
}
},
[onDelete, indexPattern]
);
return <DeleteRuntimeFieldProvider children={children} onConfirmDelete={deleteFields} />;
});
};

View file

@ -1,9 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export { getDeleteProvider, Props as DeleteProviderProps } from './get_delete_provider';

View file

@ -17,4 +17,6 @@ export {
FieldEditorContext,
} from './field_editor_flyout_content_container';
export { getDeleteFieldProvider, Props as DeleteFieldProviderProps } from './delete_field_provider';
export * from './field_format_editor';

View file

@ -29,4 +29,5 @@ export function plugin() {
// Expose types
export type { OpenFieldEditorOptions } from './open_editor';
export type { OpenFieldDeleteModalOptions } from './open_delete_modal';
export type { FieldEditorContext } from './components/field_editor_flyout_content_container';

View file

@ -0,0 +1,42 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { i18n } from '@kbn/i18n';
import { METRIC_TYPE } from '@kbn/analytics';
import { NotificationsStart } from 'src/core/public';
import { IndexPattern, UsageCollectionStart } from '../shared_imports';
import { pluginName } from '../constants';
import { DataPublicPluginStart } from '../../../data/public';
export async function removeFields(
fieldNames: string[],
indexPattern: IndexPattern,
services: {
indexPatternService: DataPublicPluginStart['indexPatterns'];
usageCollection: UsageCollectionStart;
notifications: NotificationsStart;
}
) {
fieldNames.forEach((fieldName) => {
indexPattern.removeRuntimeField(fieldName);
});
try {
services.usageCollection.reportUiCounter(pluginName, METRIC_TYPE.COUNT, 'delete_runtime');
// eslint-disable-next-line no-empty
} catch {}
try {
await services.indexPatternService.updateSavedObject(indexPattern);
} catch (e) {
const title = i18n.translate('indexPatternFieldEditor.save.deleteErrorTitle', {
defaultMessage: 'Failed to save field removal',
});
services.notifications.toasts.addError(e, { title });
}
}

View file

@ -29,6 +29,7 @@ const createSetupContract = (): Setup => {
const createStartContract = (): Start => {
return {
openEditor: jest.fn(),
openDeleteModal: jest.fn(),
fieldFormatEditors: {
getAll: jest.fn(),
getById: jest.fn(),

View file

@ -0,0 +1,88 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { CoreStart, OverlayRef } from 'src/core/public';
import {
toMountPoint,
DataPublicPluginStart,
IndexPattern,
UsageCollectionStart,
} from './shared_imports';
import { CloseEditor } from './types';
import { DeleteFieldModal } from './components/delete_field_modal';
import { removeFields } from './lib/remove_fields';
export interface OpenFieldDeleteModalOptions {
ctx: {
indexPattern: IndexPattern;
};
onDelete?: (fieldNames: string[]) => void;
fieldName: string | string[];
}
interface Dependencies {
core: CoreStart;
indexPatternService: DataPublicPluginStart['indexPatterns'];
usageCollection: UsageCollectionStart;
}
export const getFieldDeleteModalOpener = ({
core,
indexPatternService,
usageCollection,
}: Dependencies) => (options: OpenFieldDeleteModalOptions): CloseEditor => {
const { overlays, notifications } = core;
let overlayRef: OverlayRef | null = null;
const openDeleteModal = ({
onDelete,
fieldName,
ctx: { indexPattern },
}: OpenFieldDeleteModalOptions): CloseEditor => {
const fieldsToDelete = Array.isArray(fieldName) ? fieldName : [fieldName];
const closeModal = () => {
if (overlayRef) {
overlayRef.close();
overlayRef = null;
}
};
const onConfirmDelete = async () => {
closeModal();
await removeFields(fieldsToDelete, indexPattern, {
indexPatternService,
usageCollection,
notifications,
});
if (onDelete) {
onDelete(fieldsToDelete);
}
};
overlayRef = overlays.openModal(
toMountPoint(
<DeleteFieldModal
fieldsToDelete={fieldsToDelete}
closeModal={closeModal}
confirmDelete={onConfirmDelete}
/>
)
);
return closeModal;
};
return openDeleteModal(options);
};

View file

@ -19,7 +19,7 @@ import {
UsageCollectionStart,
} from './shared_imports';
import { InternalFieldType } from './types';
import { InternalFieldType, CloseEditor } from './types';
import { FieldEditorFlyoutContentContainer } from './components/field_editor_flyout_content_container';
import { PluginStart } from './types';
@ -32,7 +32,6 @@ export interface OpenFieldEditorOptions {
fieldName?: string;
}
type CloseEditor = () => void;
interface Dependencies {
core: CoreStart;
/** The search service from the data plugin */

View file

@ -25,6 +25,8 @@ import { registerTestBed } from './test_utils';
import { FieldEditorFlyoutContentContainer } from './components/field_editor_flyout_content_container';
import { IndexPatternFieldEditorPlugin } from './plugin';
import { DeleteFieldModal } from './components/delete_field_modal';
import { IndexPattern } from './shared_imports';
const noop = () => {};
@ -82,6 +84,70 @@ describe('IndexPatternFieldEditorPlugin', () => {
expect(typeof closeEditorHandler).toBe('function');
});
test('should expose a handler to open field deletion modal', async () => {
const startApi = await plugin.start(coreStart, pluginStart);
expect(startApi.openDeleteModal).toBeDefined();
});
test('should call correct services when opening the deletion modal', async () => {
const openModal = jest.fn();
const onDeleteSpy = jest.fn();
const removeFieldSpy = jest.fn();
const coreStartMocked = {
...coreStart,
overlays: {
...coreStart.overlays,
openModal,
},
};
const pluginStartMocked = {
...pluginStart,
data: {
...pluginStart.data,
indexPatterns: {
...pluginStart.data.indexPatterns,
updateSavedObject: jest.fn(),
},
},
};
const { openDeleteModal } = await plugin.start(coreStartMocked, pluginStartMocked);
const indexPatternMock = ({ removeRuntimeField: removeFieldSpy } as unknown) as IndexPattern;
openDeleteModal({
onDelete: onDeleteSpy,
ctx: { indexPattern: indexPatternMock },
fieldName: ['a', 'b', 'c'],
});
expect(openModal).toHaveBeenCalled();
const [[arg]] = openModal.mock.calls;
expect(arg.type).toBe(DeleteFieldModal);
// simulate user confirming deletion
await arg.props.confirmDelete();
// consumer should be notified
expect(onDeleteSpy).toHaveBeenCalled();
// fields should be removed on index pattern and changes persisted
expect(removeFieldSpy).toHaveBeenCalledWith('a');
expect(removeFieldSpy).toHaveBeenCalledWith('b');
expect(removeFieldSpy).toHaveBeenCalledWith('c');
expect(pluginStartMocked.data.indexPatterns.updateSavedObject).toHaveBeenLastCalledWith(
indexPatternMock
);
});
test('should return a handler to close the modal', async () => {
const { openDeleteModal } = await plugin.start(coreStart, pluginStart);
const closeModal = openDeleteModal({ fieldName: ['a'], ctx: { indexPattern: {} as any } });
expect(typeof closeModal).toBe('function');
});
test('should expose a render props component to delete runtime fields', async () => {
const { DeleteRuntimeFieldProvider } = await plugin.start(coreStart, pluginStart);

View file

@ -11,7 +11,8 @@ import { Plugin, CoreSetup, CoreStart } from 'src/core/public';
import { PluginSetup, PluginStart, SetupPlugins, StartPlugins } from './types';
import { getFieldEditorOpener } from './open_editor';
import { FormatEditorService } from './service';
import { getDeleteProvider } from './components/delete_field_provider';
import { getDeleteFieldProvider } from './components/delete_field_provider';
import { getFieldDeleteModalOpener } from './open_delete_modal';
export class IndexPatternFieldEditorPlugin
implements Plugin<PluginSetup, PluginStart, SetupPlugins, StartPlugins> {
@ -31,6 +32,11 @@ export class IndexPatternFieldEditorPlugin
application: { capabilities },
} = core;
const { data, usageCollection } = plugins;
const openDeleteModal = getFieldDeleteModalOpener({
core,
indexPatternService: data.indexPatterns,
usageCollection,
});
return {
fieldFormatEditors,
openEditor: getFieldEditorOpener({
@ -41,16 +47,13 @@ export class IndexPatternFieldEditorPlugin
search: data.search,
usageCollection,
}),
openDeleteModal,
userPermissions: {
editIndexPattern: () => {
return capabilities.management.kibana.indexPatterns;
},
},
DeleteRuntimeFieldProvider: getDeleteProvider(
data.indexPatterns,
usageCollection,
core.notifications
),
DeleteRuntimeFieldProvider: getDeleteFieldProvider(openDeleteModal),
};
}

View file

@ -15,8 +15,9 @@ import {
UsageCollectionStart,
} from './shared_imports';
import { OpenFieldEditorOptions } from './open_editor';
import { OpenFieldDeleteModalOptions } from './open_delete_modal';
import { FormatEditorServiceSetup, FormatEditorServiceStart } from './service';
import { DeleteProviderProps } from './components/delete_field_provider';
import { DeleteFieldProviderProps } from './components';
export interface PluginSetup {
fieldFormatEditors: FormatEditorServiceSetup['fieldFormatEditors'];
@ -24,11 +25,12 @@ export interface PluginSetup {
export interface PluginStart {
openEditor(options: OpenFieldEditorOptions): () => void;
openDeleteModal(options: OpenFieldDeleteModalOptions): () => void;
fieldFormatEditors: FormatEditorServiceStart['fieldFormatEditors'];
userPermissions: {
editIndexPattern: () => boolean;
};
DeleteRuntimeFieldProvider: FunctionComponent<DeleteProviderProps>;
DeleteRuntimeFieldProvider: FunctionComponent<DeleteFieldProviderProps>;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
@ -61,3 +63,5 @@ export interface EsRuntimeField {
source: string;
};
}
export type CloseEditor = () => void;