mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ML] Add Maps ui action to Index data visualizer/Discover's Field statistics (#120846)
* Add map UI actions to dv * Fix maps logo, comment * Add permission check for ui actions * Remove unnecessary json stringify because it no longer includes query object Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
47d30e4815
commit
4af89667c2
7 changed files with 115 additions and 80 deletions
|
@ -10,7 +10,8 @@
|
|||
"embeddable",
|
||||
"share",
|
||||
"discover",
|
||||
"fileUpload"
|
||||
"fileUpload",
|
||||
"uiActions"
|
||||
],
|
||||
"optionalPlugins": [
|
||||
"security",
|
||||
|
@ -26,7 +27,8 @@
|
|||
"maps",
|
||||
"esUiShared",
|
||||
"fieldFormats",
|
||||
"charts"
|
||||
"charts",
|
||||
"uiActions"
|
||||
],
|
||||
"extraPublicDirs": [
|
||||
"common"
|
||||
|
|
|
@ -17,14 +17,16 @@ import {
|
|||
dataVisualizerRefresh$,
|
||||
Refresh,
|
||||
} from '../../../../index_data_visualizer/services/timefilter_refresh_service';
|
||||
import { JOB_FIELD_TYPES } from '../../../../../../common';
|
||||
import { VISUALIZE_GEO_FIELD_TRIGGER } from '../../../../../../../../../src/plugins/ui_actions/public';
|
||||
|
||||
export function getActions(
|
||||
indexPattern: IndexPattern,
|
||||
services: Partial<DataVisualizerKibanaReactContextValue['services']>,
|
||||
combinedQuery: CombinedQuery,
|
||||
actionFlyoutRef: MutableRefObject<(() => void | undefined) | undefined>
|
||||
dataViewEditorRef: MutableRefObject<(() => void | undefined) | undefined> | undefined
|
||||
): Array<Action<FieldVisConfig>> {
|
||||
const { lens: lensPlugin, data } = services;
|
||||
const { lens: lensPlugin, maps: mapsPlugin, data } = services;
|
||||
|
||||
const actions: Array<Action<FieldVisConfig>> = [];
|
||||
const filters = data?.query.filterManager.getFilters() ?? [];
|
||||
|
@ -36,7 +38,7 @@ export function getActions(
|
|||
dataVisualizerRefresh$.next(refresh);
|
||||
};
|
||||
// Navigate to Lens with prefilled chart for data field
|
||||
if (lensPlugin !== undefined) {
|
||||
if (services.application?.capabilities?.visualize?.show === true && lensPlugin !== undefined) {
|
||||
const canUseLensEditor = lensPlugin?.canUseEditor();
|
||||
actions.push({
|
||||
name: i18n.translate('xpack.dataVisualizer.index.dataGrid.exploreInLensTitle', {
|
||||
|
@ -62,53 +64,93 @@ export function getActions(
|
|||
});
|
||||
}
|
||||
|
||||
// Allow to edit data view field
|
||||
if (services.dataViewFieldEditor?.userPermissions.editIndexPattern()) {
|
||||
if (
|
||||
services?.uiActions &&
|
||||
mapsPlugin &&
|
||||
services.application?.capabilities?.maps?.show === true
|
||||
) {
|
||||
actions.push({
|
||||
name: i18n.translate('xpack.dataVisualizer.index.dataGrid.editDataViewFieldTitle', {
|
||||
defaultMessage: 'Edit data view field',
|
||||
name: i18n.translate('xpack.dataVisualizer.index.dataGrid.exploreInMapsTitle', {
|
||||
defaultMessage: 'Explore in Maps',
|
||||
}),
|
||||
description: i18n.translate(
|
||||
'xpack.dataVisualizer.index.dataGrid.editDataViewFieldDescription',
|
||||
{
|
||||
defaultMessage: 'Edit data view field',
|
||||
}
|
||||
),
|
||||
type: 'icon',
|
||||
icon: 'indexEdit',
|
||||
onClick: (item: FieldVisConfig) => {
|
||||
actionFlyoutRef.current = services.dataViewFieldEditor?.openEditor({
|
||||
ctx: { dataView: indexPattern },
|
||||
fieldName: item.fieldName,
|
||||
onSave: refreshPage,
|
||||
});
|
||||
},
|
||||
'data-test-subj': 'dataVisualizerActionEditIndexPatternFieldButton',
|
||||
});
|
||||
actions.push({
|
||||
name: i18n.translate('xpack.dataVisualizer.index.dataGrid.deleteDataViewFieldTitle', {
|
||||
defaultMessage: 'Delete data view field',
|
||||
description: i18n.translate('xpack.dataVisualizer.index.dataGrid.exploreInMapsDescription', {
|
||||
defaultMessage: 'Explore in Maps',
|
||||
}),
|
||||
description: i18n.translate(
|
||||
'xpack.dataVisualizer.index.dataGrid.deleteIndexPatternFieldDescription',
|
||||
{
|
||||
defaultMessage: 'Delete data view field',
|
||||
}
|
||||
),
|
||||
type: 'icon',
|
||||
icon: 'trash',
|
||||
icon: 'gisApp',
|
||||
available: (item: FieldVisConfig) => {
|
||||
return item.deletable === true;
|
||||
return item.type === JOB_FIELD_TYPES.GEO_POINT || item.type === JOB_FIELD_TYPES.GEO_SHAPE;
|
||||
},
|
||||
onClick: (item: FieldVisConfig) => {
|
||||
actionFlyoutRef.current = services.dataViewFieldEditor?.openDeleteModal({
|
||||
ctx: { dataView: indexPattern },
|
||||
fieldName: item.fieldName!,
|
||||
onDelete: refreshPage,
|
||||
});
|
||||
onClick: async (item: FieldVisConfig) => {
|
||||
if (services?.uiActions && indexPattern) {
|
||||
const triggerOptions = {
|
||||
indexPatternId: indexPattern.id,
|
||||
fieldName: item.fieldName,
|
||||
contextualFields: [],
|
||||
};
|
||||
const testActions = await services?.uiActions.getTriggerCompatibleActions(
|
||||
VISUALIZE_GEO_FIELD_TRIGGER,
|
||||
triggerOptions
|
||||
);
|
||||
|
||||
if (testActions.length > 0 && testActions[0] !== undefined) {
|
||||
services?.uiActions.getTrigger(VISUALIZE_GEO_FIELD_TRIGGER).exec(triggerOptions);
|
||||
}
|
||||
}
|
||||
},
|
||||
'data-test-subj': 'dataVisualizerActionDeleteIndexPatternFieldButton',
|
||||
'data-test-subj': 'dataVisualizerActionViewInMapsButton',
|
||||
});
|
||||
}
|
||||
|
||||
if (dataViewEditorRef !== undefined) {
|
||||
// Allow to edit data view field
|
||||
if (services.dataViewFieldEditor?.userPermissions.editIndexPattern()) {
|
||||
actions.push({
|
||||
name: i18n.translate('xpack.dataVisualizer.index.dataGrid.editDataViewFieldTitle', {
|
||||
defaultMessage: 'Edit data view field',
|
||||
}),
|
||||
description: i18n.translate(
|
||||
'xpack.dataVisualizer.index.dataGrid.editDataViewFieldDescription',
|
||||
{
|
||||
defaultMessage: 'Edit data view field',
|
||||
}
|
||||
),
|
||||
type: 'icon',
|
||||
icon: 'indexEdit',
|
||||
onClick: (item: FieldVisConfig) => {
|
||||
dataViewEditorRef.current = services.dataViewFieldEditor?.openEditor({
|
||||
ctx: { dataView: indexPattern },
|
||||
fieldName: item.fieldName,
|
||||
onSave: refreshPage,
|
||||
});
|
||||
},
|
||||
'data-test-subj': 'dataVisualizerActionEditIndexPatternFieldButton',
|
||||
});
|
||||
actions.push({
|
||||
name: i18n.translate('xpack.dataVisualizer.index.dataGrid.deleteDataViewFieldTitle', {
|
||||
defaultMessage: 'Delete data view field',
|
||||
}),
|
||||
description: i18n.translate(
|
||||
'xpack.dataVisualizer.index.dataGrid.deleteIndexPatternFieldDescription',
|
||||
{
|
||||
defaultMessage: 'Delete data view field',
|
||||
}
|
||||
),
|
||||
type: 'icon',
|
||||
icon: 'trash',
|
||||
available: (item: FieldVisConfig) => {
|
||||
return item.deletable === true;
|
||||
},
|
||||
onClick: (item: FieldVisConfig) => {
|
||||
dataViewEditorRef.current = services.dataViewFieldEditor?.openDeleteModal({
|
||||
ctx: { dataView: indexPattern },
|
||||
fieldName: item.fieldName!,
|
||||
onDelete: refreshPage,
|
||||
});
|
||||
},
|
||||
'data-test-subj': 'dataVisualizerActionDeleteIndexPatternFieldButton',
|
||||
});
|
||||
}
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ import {
|
|||
EuiSpacer,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { EuiTableActionsColumnType } from '@elastic/eui/src/components/basic_table/table_types';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { Required } from 'utility-types';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Filter } from '@kbn/es-query';
|
||||
|
@ -34,7 +32,6 @@ import {
|
|||
import { FieldVisConfig } from '../../../common/components/stats_table/types';
|
||||
import type { TotalFieldsStats } from '../../../common/components/stats_table/components/field_count_stats';
|
||||
import { OverallStats } from '../../types/overall_stats';
|
||||
import { getActions } from '../../../common/components/field_data_row/action_menu';
|
||||
import { IndexBasedDataVisualizerExpandedRow } from '../../../common/components/expanded_row/index_based_expanded_row';
|
||||
import { DATA_VISUALIZER_INDEX_VIEWER } from '../../constants/index_data_visualizer_viewer';
|
||||
import { DataVisualizerIndexBasedAppState } from '../../types/index_data_visualizer_state';
|
||||
|
@ -232,6 +229,7 @@ export const IndexDataVisualizerView: FC<IndexDataVisualizerViewProps> = (dataVi
|
|||
indexPattern: currentIndexPattern,
|
||||
savedSearch: currentSavedSearch,
|
||||
visibleFieldNames,
|
||||
allowEditDataView: true,
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentIndexPattern.id, currentSavedSearch?.id, visibleFieldNames]);
|
||||
|
@ -247,6 +245,7 @@ export const IndexDataVisualizerView: FC<IndexDataVisualizerViewProps> = (dataVi
|
|||
timefilter,
|
||||
setLastRefresh,
|
||||
progress,
|
||||
extendedColumns,
|
||||
} = useDataVisualizerGridData(input, dataVisualizerListState, setGlobalState);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -381,34 +380,13 @@ export const IndexDataVisualizerView: FC<IndexDataVisualizerViewProps> = (dataVi
|
|||
};
|
||||
}, []);
|
||||
|
||||
// Inject custom action column for the index based visualizer
|
||||
// Hide the column completely if no access to any of the plugins
|
||||
const extendedColumns = useMemo(() => {
|
||||
const actions = getActions(
|
||||
currentIndexPattern,
|
||||
services,
|
||||
{
|
||||
searchQueryLanguage,
|
||||
searchString,
|
||||
},
|
||||
actionFlyoutRef
|
||||
);
|
||||
if (!Array.isArray(actions) || actions.length < 1) return;
|
||||
|
||||
const actionColumn: EuiTableActionsColumnType<FieldVisConfig> = {
|
||||
name: (
|
||||
<FormattedMessage
|
||||
id="xpack.dataVisualizer.index.dataGrid.actionsColumnLabel"
|
||||
defaultMessage="Actions"
|
||||
/>
|
||||
),
|
||||
actions,
|
||||
width: '100px',
|
||||
};
|
||||
|
||||
return [actionColumn];
|
||||
}, [currentIndexPattern, services, searchQueryLanguage, searchString]);
|
||||
|
||||
useEffect(() => {
|
||||
// Update data query manager if input string is updated
|
||||
data?.query.queryString.setQuery({
|
||||
query: searchString,
|
||||
language: searchQueryLanguage,
|
||||
});
|
||||
}, [data, searchQueryLanguage, searchString]);
|
||||
const helpLink = docLinks.links.ml.guide;
|
||||
|
||||
return (
|
||||
|
|
|
@ -49,6 +49,7 @@ export interface DataVisualizerGridInput {
|
|||
visibleFieldNames?: string[];
|
||||
filters?: Filter[];
|
||||
showPreviewByDefault?: boolean;
|
||||
allowEditDataView?: boolean;
|
||||
/**
|
||||
* Callback to add a filter to filter bar
|
||||
*/
|
||||
|
|
|
@ -492,12 +492,12 @@ export const useDataVisualizerGridData = (
|
|||
const extendedColumns = useMemo(() => {
|
||||
const actions = getActions(
|
||||
input.indexPattern,
|
||||
{ lens: services.lens },
|
||||
services,
|
||||
{
|
||||
searchQueryLanguage,
|
||||
searchString,
|
||||
},
|
||||
actionFlyoutRef
|
||||
input.allowEditDataView ? actionFlyoutRef : undefined
|
||||
);
|
||||
if (!Array.isArray(actions) || actions.length < 1) return;
|
||||
|
||||
|
@ -510,7 +510,7 @@ export const useDataVisualizerGridData = (
|
|||
};
|
||||
|
||||
return [actionColumn];
|
||||
}, [input.indexPattern, services, searchQueryLanguage, searchString]);
|
||||
}, [input.indexPattern, services, searchQueryLanguage, searchString, input.allowEditDataView]);
|
||||
|
||||
return {
|
||||
progress: combinedProgress,
|
||||
|
|
|
@ -178,8 +178,17 @@ export const DataVisualizerUrlStateContextProvider: FC<DataVisualizerUrlStateCon
|
|||
|
||||
export const IndexDataVisualizer: FC<{ additionalLinks: ResultLink[] }> = ({ additionalLinks }) => {
|
||||
const coreStart = getCoreStart();
|
||||
const { data, maps, embeddable, share, security, fileUpload, lens, dataViewFieldEditor } =
|
||||
getPluginsStart();
|
||||
const {
|
||||
data,
|
||||
maps,
|
||||
embeddable,
|
||||
share,
|
||||
security,
|
||||
fileUpload,
|
||||
lens,
|
||||
dataViewFieldEditor,
|
||||
uiActions,
|
||||
} = getPluginsStart();
|
||||
const services = {
|
||||
data,
|
||||
maps,
|
||||
|
@ -189,6 +198,7 @@ export const IndexDataVisualizer: FC<{ additionalLinks: ResultLink[] }> = ({ add
|
|||
fileUpload,
|
||||
lens,
|
||||
dataViewFieldEditor,
|
||||
uiActions,
|
||||
...coreStart,
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import { getMaxBytesFormatted } from './application/common/util/get_max_bytes';
|
|||
import { registerHomeAddData, registerHomeFeatureCatalogue } from './register_home';
|
||||
import { registerEmbeddables } from './application/index_data_visualizer/embeddables';
|
||||
import { FieldFormatsStart } from '../../../../src/plugins/field_formats/public';
|
||||
import { UiActionsStart } from '../../../../src/plugins/ui_actions/public';
|
||||
|
||||
export interface DataVisualizerSetupDependencies {
|
||||
home?: HomePublicPluginSetup;
|
||||
|
@ -38,6 +39,7 @@ export interface DataVisualizerStartDependencies {
|
|||
lens?: LensPublicStart;
|
||||
dataViewFieldEditor?: IndexPatternFieldEditorStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
uiActions?: UiActionsStart;
|
||||
}
|
||||
|
||||
export type DataVisualizerPluginSetup = ReturnType<DataVisualizerPlugin['setup']>;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue