Skip to content

Commit

Permalink
Add imperative delete field api (#93181)
Browse files Browse the repository at this point in the history
  • Loading branch information
flash1293 authored Mar 8, 2021
1 parent baf0b35 commit 68ed17a
Show file tree
Hide file tree
Showing 16 changed files with 496 additions and 216 deletions.
120 changes: 114 additions & 6 deletions api_docs/index_pattern_field_editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -369,15 +433,59 @@
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 26
"lineNumber": 27
}
}
],
"tags": [],
"returnComment": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"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": 26
"lineNumber": 28
}
},
{
Expand All @@ -388,7 +496,7 @@
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 27
"lineNumber": 29
},
"signature": [
"{ getAll: () => typeof ",
Expand Down Expand Up @@ -418,7 +526,7 @@
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 28
"lineNumber": 30
},
"signature": [
"{ editIndexPattern: () => boolean; }"
Expand All @@ -432,7 +540,7 @@
"description": [],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 31
"lineNumber": 33
},
"signature": [
"React.FunctionComponent<",
Expand All @@ -449,7 +557,7 @@
],
"source": {
"path": "src/plugins/index_pattern_field_editor/public/types.ts",
"lineNumber": 25
"lineNumber": 26
},
"lifecycle": "start",
"initialIsOpen": true
Expand Down
26 changes: 23 additions & 3 deletions src/plugins/index_pattern_field_editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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>
);
}
Original file line number Diff line number Diff line change
@@ -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)}</>;
});
};
Loading

0 comments on commit 68ed17a

Please sign in to comment.