Skip to content

Commit

Permalink
[ML] Add Create a data view button to index or saved search selector …
Browse files Browse the repository at this point in the history
…in ML pages and Transforms management (#166668)

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
qn895 and kibanamachine authored Oct 2, 2023
1 parent ede8d61 commit 007c341
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 24 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/ml/public/application/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ const App: FC<AppProps> = ({ coreStart, deps, appMountParams, isServerless, mlFe
kibanaVersion: deps.kibanaVersion,
share: deps.share,
data: deps.data,
dataViewEditor: deps.dataViewEditor,
security: deps.security,
licenseManagement: deps.licenseManagement,
storage: localStorage,
embeddable: deps.embeddable,
maps: deps.maps,
triggersActionsUi: deps.triggersActionsUi,
dataViewEditor: deps.dataViewEditor,
dataVisualizer: deps.dataVisualizer,
usageCollection: deps.usageCollection,
fieldFormats: deps.fieldFormats,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { EuiButton } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import React, { useCallback, useEffect, useRef } from 'react';
import { useMlKibana } from '../../contexts/kibana';

export const CreateDataViewButton = ({
onDataViewCreated,
allowAdHocDataView = false,
}: {
onDataViewCreated: (id: string, type: string, name?: string) => void;
allowAdHocDataView?: boolean;
}) => {
const { dataViewEditor } = useMlKibana().services;
const canEditDataView = Boolean(dataViewEditor?.userPermissions.editDataView());
const closeDataViewEditorRef = useRef<() => void | undefined>();

const createNewDataView = useCallback(() => {
closeDataViewEditorRef.current = dataViewEditor?.openEditor({
onSave: async (dataView) => {
if (dataView.id && onDataViewCreated) {
onDataViewCreated(dataView.id, 'index-pattern', dataView.name);
}
},

allowAdHocDataView,
});
}, [onDataViewCreated, dataViewEditor, allowAdHocDataView]);

useEffect(function cleanUpFlyout() {
return () => {
// Close the editor when unmounting
if (closeDataViewEditorRef.current) {
closeDataViewEditorRef.current();
}
};
}, []);

return canEditDataView ? (
<EuiButton
onClick={createNewDataView}
fill
iconType="plusInCircle"
data-test-subj="newDataViewButton"
disabled={!canEditDataView}
>
<FormattedMessage
id="xpack.ml.savedObjectFinder.createADataView"
defaultMessage="Create a data view"
/>
</EuiButton>
) : null;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export { CreateDataViewButton } from './create_data_view_button';
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-manag
import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public';
import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public';
import { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
import type { MlServicesContext } from '../../app';

interface StartPlugins {
data: DataPublicPluginStart;
dataViews: DataViewsPublicPluginStart;
dataViewEditor: DataViewEditorStart;
dataViews: DataViewsPublicPluginStart;
security?: SecurityPluginSetup;
licenseManagement?: LicenseManagementUIPluginSetup;
share: SharePluginStart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n';
import { getNestedProperty } from '@kbn/ml-nested-property';
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
import type { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
import { CreateDataViewButton } from '../../../../../components/create_data_view_button';
import { useMlKibana, useNavigateToPath } from '../../../../../contexts/kibana';
import { useToastNotificationService } from '../../../../../services/toast_notification_service';
import {
Expand Down Expand Up @@ -38,16 +39,16 @@ export const SourceSelection: FC = () => {
const onSearchSelected = async (
id: string,
type: string,
fullName: string,
savedObject: SavedObjectCommon
fullName?: string,
savedObject?: SavedObjectCommon
) => {
// Kibana data views including `:` are cross-cluster search indices
// and are not supported by Data Frame Analytics yet. For saved searches
// and data views that use cross-cluster search we intercept
// the selection before redirecting and show an error callout instead.
let dataViewName = '';

if (type === 'index-pattern') {
if (type === 'index-pattern' && savedObject) {
dataViewName = getNestedProperty(savedObject, 'attributes.title');
} else if (type === 'search') {
try {
Expand All @@ -71,7 +72,7 @@ export const SourceSelection: FC = () => {
}
}

if (isCcsIndexPattern(dataViewName)) {
if (isCcsIndexPattern(dataViewName) && savedObject) {
setIsCcsCallOut(true);
if (type === 'search') {
setCcsCallOutBodyText(
Expand Down Expand Up @@ -157,7 +158,9 @@ export const SourceSelection: FC = () => {
contentClient: contentManagement.client,
uiSettings,
}}
/>
>
<CreateDataViewButton onDataViewCreated={onSearchSelected} allowAdHocDataView={true} />
</SavedObjectFinder>
</EuiPanel>
</EuiPageBody>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
* 2.0.
*/

import React, { FC } from 'react';
import React, { FC, useCallback } from 'react';
import { EuiPageBody, EuiPanel } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
import { CreateDataViewButton } from '../../../../components/create_data_view_button';
import { useMlKibana, useNavigateToPath } from '../../../../contexts/kibana';
import { MlPageHeader } from '../../../../components/page_header';

Expand All @@ -23,13 +24,16 @@ export const Page: FC<PageProps> = ({ nextStepPath }) => {
const { contentManagement, uiSettings } = useMlKibana().services;
const navigateToPath = useNavigateToPath();

const onObjectSelection = (id: string, type: string) => {
navigateToPath(
`${nextStepPath}?${type === 'index-pattern' ? 'index' : 'savedSearchId'}=${encodeURIComponent(
id
)}`
);
};
const onObjectSelection = useCallback(
(id: string, type: string, name?: string) => {
navigateToPath(
`${nextStepPath}?${
type === 'index-pattern' ? 'index' : 'savedSearchId'
}=${encodeURIComponent(id)}`
);
},
[navigateToPath, nextStepPath]
);

return (
<div data-test-subj="mlPageSourceSelection">
Expand Down Expand Up @@ -75,7 +79,9 @@ export const Page: FC<PageProps> = ({ nextStepPath }) => {
contentClient: contentManagement.client,
uiSettings,
}}
/>
>
<CreateDataViewButton onDataViewCreated={onObjectSelection} />
</SavedObjectFinder>
</EuiPanel>
</EuiPageBody>
</div>
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/transform/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"contentManagement",
],
"optionalPlugins": [
"dataViewEditor",
"security",
"usageCollection",
"spaces",
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/transform/public/app/app_dependencies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { ChartsPluginStart } from '@kbn/charts-plugin/public';
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import type { SettingsStart } from '@kbn/core-ui-settings-browser';
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
import type { GetMlSharedImportsReturnType } from '../shared_imports';

export interface AppDependencies {
Expand All @@ -45,6 +46,7 @@ export interface AppDependencies {
charts: ChartsPluginStart;
chrome: ChromeStart;
data: DataPublicPluginStart;
dataViewEditor?: DataViewEditorStart;
dataViews: DataViewsPublicPluginStart;
docLinks: DocLinksStart;
fieldFormats: FieldFormatsStart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export async function mountManagementSection(
const {
data,
dataViews,
dataViewEditor,
share,
spaces,
triggersActionsUi,
Expand All @@ -69,6 +70,7 @@ export async function mountManagementSection(
application,
chrome,
data,
dataViewEditor,
dataViews,
docLinks,
http,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,49 @@
* 2.0.
*/

import { EuiModalBody, EuiModalHeader, EuiModalHeaderTitle } from '@elastic/eui';
import { EuiButton, EuiModalBody, EuiModalHeader, EuiModalHeaderTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React, { type FC } from 'react';
import React, { type FC, Fragment, useCallback, useEffect, useRef } from 'react';

import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
import { useAppDependencies } from '../../../../app_dependencies';

interface SearchSelectionProps {
onSearchSelected: (searchId: string, searchType: string) => void;
onCloseModal: () => void;
}

const fixedPageSize: number = 8;

export const SearchSelection: FC<SearchSelectionProps> = ({ onSearchSelected }) => {
const { contentManagement, uiSettings } = useAppDependencies();
export const SearchSelection: FC<SearchSelectionProps> = ({ onSearchSelected, onCloseModal }) => {
const { contentManagement, uiSettings, dataViewEditor } = useAppDependencies();

const canEditDataView = Boolean(dataViewEditor?.userPermissions.editDataView());

const closeDataViewEditor = useRef<() => void | undefined>();

const createNewDataView = useCallback(() => {
onCloseModal();
closeDataViewEditor.current = dataViewEditor?.openEditor({
onSave: async (dataView) => {
if (dataView.id) {
onSearchSelected(dataView.id, 'index-pattern');
}
},

allowAdHocDataView: true,
});
}, [dataViewEditor, onCloseModal, onSearchSelected]);

useEffect(function cleanUpFlyout() {
return () => {
// Close the editor when unmounting
if (closeDataViewEditor.current) {
closeDataViewEditor.current();
}
};
}, []);

return (
<>
Expand Down Expand Up @@ -72,7 +99,24 @@ export const SearchSelection: FC<SearchSelectionProps> = ({ onSearchSelected })
]}
fixedPageSize={fixedPageSize}
services={{ contentClient: contentManagement.client, uiSettings }}
/>
>
{canEditDataView ? (
<EuiButton
onClick={createNewDataView}
fill
iconType="plusInCircle"
data-test-subj="newDataViewButton"
disabled={!canEditDataView}
>
<FormattedMessage
id="xpack.transform.newTransform.searchSelection.createADataView"
defaultMessage="Create a data view"
/>
</EuiButton>
) : (
<Fragment />
)}
</SavedObjectFinder>
</EuiModalBody>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ export const TransformManagement: FC = () => {
className="transformCreateTransformSearchDialog"
data-test-subj="transformSelectSourceModal"
>
<SearchSelection onSearchSelected={onSearchSelected} />
<SearchSelection onSearchSelected={onSearchSelected} onCloseModal={onCloseModal} />
</EuiModal>
)}
</>
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/transform/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-manag
import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public';
import type { PluginInitializerContext } from '@kbn/core/public';
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
import { registerFeature } from './register_feature';
import { getTransformHealthRuleType } from './alerting';

export interface PluginsDependencies {
charts: ChartsPluginStart;
data: DataPublicPluginStart;
dataViewEditor?: DataViewEditorStart;
unifiedSearch: UnifiedSearchPublicPluginStart;
dataViews: DataViewsPublicPluginStart;
management: ManagementSetup;
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/transform/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
"@kbn/ebt-tools",
"@kbn/content-management-plugin",
"@kbn/react-kibana-mount",
"@kbn/core-plugins-server"
"@kbn/core-plugins-server",
"@kbn/data-view-editor-plugin"
],
"exclude": [
"target/**/*",
Expand Down

0 comments on commit 007c341

Please sign in to comment.