mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
parent
c20815b070
commit
3b37b777cf
9 changed files with 310 additions and 0 deletions
7
examples/index_pattern_field_editor_example/README.md
Normal file
7
examples/index_pattern_field_editor_example/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
## index pattern field editor example
|
||||
|
||||
This example index pattern field editor app shows how to:
|
||||
- Edit index pattern fields via flyout
|
||||
- Delete index pattern runtime fields with modal confirm prompt
|
||||
|
||||
To run this example, use the command `yarn start --run-examples`.
|
10
examples/index_pattern_field_editor_example/kibana.json
Normal file
10
examples/index_pattern_field_editor_example/kibana.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "indexPatternFieldEditorExample",
|
||||
"version": "0.0.1",
|
||||
"kibanaVersion": "kibana",
|
||||
"server": false,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["data", "indexPatternFieldEditor", "developerExamples"],
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": []
|
||||
}
|
145
examples/index_pattern_field_editor_example/public/app.tsx
Normal file
145
examples/index_pattern_field_editor_example/public/app.tsx
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* 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 } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {
|
||||
EuiPage,
|
||||
EuiPageHeader,
|
||||
EuiPageBody,
|
||||
EuiPageContent,
|
||||
EuiPageContentBody,
|
||||
EuiButton,
|
||||
EuiInMemoryTable,
|
||||
EuiText,
|
||||
DefaultItemAction,
|
||||
} from '@elastic/eui';
|
||||
import { AppMountParameters } from '../../../src/core/public';
|
||||
import {
|
||||
DataPublicPluginStart,
|
||||
IndexPattern,
|
||||
IndexPatternField,
|
||||
} from '../../../src/plugins/data/public';
|
||||
import { IndexPatternFieldEditorStart } from '../../../src/plugins/index_pattern_field_editor/public';
|
||||
|
||||
interface Props {
|
||||
indexPattern?: IndexPattern;
|
||||
indexPatternFieldEditor: IndexPatternFieldEditorStart;
|
||||
}
|
||||
|
||||
const IndexPatternFieldEditorExample = ({ indexPattern, indexPatternFieldEditor }: Props) => {
|
||||
const [fields, setFields] = useState<IndexPatternField[]>(
|
||||
indexPattern?.getNonScriptedFields() || []
|
||||
);
|
||||
const refreshFields = () => setFields(indexPattern?.getNonScriptedFields() || []);
|
||||
const columns = [
|
||||
{
|
||||
field: 'name',
|
||||
name: 'Field name',
|
||||
},
|
||||
{
|
||||
name: 'Actions',
|
||||
actions: [
|
||||
{
|
||||
name: 'Edit',
|
||||
description: 'Edit this field',
|
||||
icon: 'pencil',
|
||||
type: 'icon',
|
||||
'data-test-subj': 'editField',
|
||||
onClick: (fld: IndexPatternField) =>
|
||||
indexPatternFieldEditor.openEditor({
|
||||
ctx: { indexPattern: indexPattern! },
|
||||
fieldName: fld.name,
|
||||
onSave: refreshFields,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
description: 'Delete this field',
|
||||
icon: 'trash',
|
||||
type: 'icon',
|
||||
'data-test-subj': 'deleteField',
|
||||
available: (fld) => !!fld.runtimeField,
|
||||
onClick: (fld: IndexPatternField) =>
|
||||
indexPatternFieldEditor.openDeleteModal({
|
||||
fieldName: fld.name,
|
||||
ctx: {
|
||||
indexPattern: indexPattern!,
|
||||
},
|
||||
onDelete: refreshFields,
|
||||
}),
|
||||
},
|
||||
] as Array<DefaultItemAction<IndexPatternField>>,
|
||||
},
|
||||
];
|
||||
|
||||
const content = indexPattern ? (
|
||||
<>
|
||||
<EuiText data-test-subj="indexPatternTitle">Index pattern: {indexPattern?.title}</EuiText>
|
||||
<div>
|
||||
<EuiButton
|
||||
onClick={() =>
|
||||
indexPatternFieldEditor.openEditor({
|
||||
ctx: { indexPattern: indexPattern! },
|
||||
onSave: refreshFields,
|
||||
})
|
||||
}
|
||||
data-test-subj="addField"
|
||||
>
|
||||
Add field
|
||||
</EuiButton>
|
||||
</div>
|
||||
<EuiInMemoryTable<IndexPatternField>
|
||||
items={fields}
|
||||
columns={columns}
|
||||
pagination={true}
|
||||
hasActions={true}
|
||||
sorting={{
|
||||
sort: {
|
||||
field: 'name',
|
||||
direction: 'asc',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<p>Please create an index pattern</p>
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiPage>
|
||||
<EuiPageBody>
|
||||
<EuiPageHeader>Index pattern field editor demo</EuiPageHeader>
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody>{content}</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</EuiPageBody>
|
||||
</EuiPage>
|
||||
);
|
||||
};
|
||||
|
||||
interface RenderAppDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
indexPatternFieldEditor: IndexPatternFieldEditorStart;
|
||||
}
|
||||
|
||||
export const renderApp = async (
|
||||
{ data, indexPatternFieldEditor }: RenderAppDependencies,
|
||||
{ element }: AppMountParameters
|
||||
) => {
|
||||
const indexPattern = (await data.indexPatterns.getDefault()) || undefined;
|
||||
ReactDOM.render(
|
||||
<IndexPatternFieldEditorExample
|
||||
indexPattern={indexPattern}
|
||||
indexPatternFieldEditor={indexPatternFieldEditor}
|
||||
/>,
|
||||
element
|
||||
);
|
||||
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
11
examples/index_pattern_field_editor_example/public/index.ts
Normal file
11
examples/index_pattern_field_editor_example/public/index.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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 { IndexPatternFieldEditorPlugin } from './plugin';
|
||||
|
||||
export const plugin = () => new IndexPatternFieldEditorPlugin();
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '../../../src/core/public';
|
||||
import { DeveloperExamplesSetup } from '../../developer_examples/public';
|
||||
import { DataPublicPluginStart } from '../../../src/plugins/data/public';
|
||||
import { IndexPatternFieldEditorStart } from '../../../src/plugins/index_pattern_field_editor/public';
|
||||
|
||||
interface StartDeps {
|
||||
data: DataPublicPluginStart;
|
||||
indexPatternFieldEditor: IndexPatternFieldEditorStart;
|
||||
}
|
||||
|
||||
interface SetupDeps {
|
||||
developerExamples: DeveloperExamplesSetup;
|
||||
}
|
||||
|
||||
export class IndexPatternFieldEditorPlugin implements Plugin<void, void, SetupDeps, StartDeps> {
|
||||
public setup(core: CoreSetup<StartDeps>, deps: SetupDeps) {
|
||||
core.application.register({
|
||||
id: 'indexPatternFieldEditorExample',
|
||||
title: 'Index pattern field editor example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
async mount(params: AppMountParameters) {
|
||||
const [, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./app');
|
||||
return renderApp(depsStart, params);
|
||||
},
|
||||
});
|
||||
|
||||
deps.developerExamples.register({
|
||||
appId: 'indexPatternFieldEditorExample',
|
||||
title: 'Index pattern field editor',
|
||||
description: `IndexPatternFieldEditor provides a UI for editing index pattern fields directly from Kibana apps. This example plugin demonstrates integration.`,
|
||||
links: [
|
||||
{
|
||||
label: 'README',
|
||||
href:
|
||||
'https://github.com/elastic/kibana/blob/master/src/plugins/index_pattern_field_editor/README.md',
|
||||
iconType: 'logoGithub',
|
||||
size: 's',
|
||||
target: '_blank',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
public start() {}
|
||||
|
||||
public stop() {}
|
||||
}
|
18
examples/index_pattern_field_editor_example/tsconfig.json
Normal file
18
examples/index_pattern_field_editor_example/tsconfig.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"public/**/*.ts",
|
||||
"public/**/*.tsx",
|
||||
"../../typings/**/*",
|
||||
],
|
||||
"exclude": [],
|
||||
"references": [
|
||||
{ "path": "../../src/core/tsconfig.json" },
|
||||
{ "path": "../../src/plugins/kibana_react/tsconfig.json" },
|
||||
]
|
||||
}
|
|
@ -28,6 +28,7 @@ export default async function ({ readConfigFile }) {
|
|||
require.resolve('./state_sync'),
|
||||
require.resolve('./routing'),
|
||||
require.resolve('./expressions_explorer'),
|
||||
require.resolve('./index_pattern_field_editor_example'),
|
||||
],
|
||||
services: {
|
||||
...functionalConfig.get('services'),
|
||||
|
|
38
test/examples/index_pattern_field_editor_example/index.ts
Normal file
38
test/examples/index_pattern_field_editor_example/index.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 { PluginFunctionalProviderContext } from 'test/plugin_functional/services';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function ({
|
||||
getService,
|
||||
getPageObjects,
|
||||
loadTestFile,
|
||||
}: PluginFunctionalProviderContext) {
|
||||
const browser = getService('browser');
|
||||
const es = getService('es');
|
||||
const PageObjects = getPageObjects(['common', 'header', 'settings']);
|
||||
|
||||
describe('index pattern field editor example', function () {
|
||||
this.tags('ciGroup2');
|
||||
before(async () => {
|
||||
await browser.setWindowSize(1300, 900);
|
||||
await es.transport.request({
|
||||
path: '/blogs/_doc',
|
||||
method: 'POST',
|
||||
body: { user: 'matt', message: 20 },
|
||||
});
|
||||
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.createIndexPattern('blogs', null);
|
||||
await PageObjects.common.navigateToApp('indexPatternFieldEditorExample');
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./index_pattern_field_editor_example'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { PluginFunctionalProviderContext } from 'test/plugin_functional/services';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
describe('', () => {
|
||||
it('finds an index pattern', async () => {
|
||||
await testSubjects.existOrFail('indexPatternTitle');
|
||||
});
|
||||
it('opens the field editor', async () => {
|
||||
await testSubjects.click('addField');
|
||||
await testSubjects.existOrFail('flyoutTitle');
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue