Skip to content

Commit

Permalink
[ML] Add Maps ui action to Index data visualizer/Discover's Field sta…
Browse files Browse the repository at this point in the history
…tistics (#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 <[email protected]>
  • Loading branch information
qn895 and kibanamachine authored Dec 14, 2021
1 parent 47d30e4 commit 4af8966
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 80 deletions.
6 changes: 4 additions & 2 deletions x-pack/plugins/data_visualizer/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"embeddable",
"share",
"discover",
"fileUpload"
"fileUpload",
"uiActions"
],
"optionalPlugins": [
"security",
Expand All @@ -26,7 +27,8 @@
"maps",
"esUiShared",
"fieldFormats",
"charts"
"charts",
"uiActions"
],
"extraPublicDirs": [
"common"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() ?? [];
Expand All @@ -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', {
Expand All @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -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]);
Expand All @@ -247,6 +245,7 @@ export const IndexDataVisualizerView: FC<IndexDataVisualizerViewProps> = (dataVi
timefilter,
setLastRefresh,
progress,
extendedColumns,
} = useDataVisualizerGridData(input, dataVisualizerListState, setGlobalState);

useEffect(() => {
Expand Down Expand Up @@ -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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface DataVisualizerGridInput {
visibleFieldNames?: string[];
filters?: Filter[];
showPreviewByDefault?: boolean;
allowEditDataView?: boolean;
/**
* Callback to add a filter to filter bar
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -510,7 +510,7 @@ export const useDataVisualizerGridData = (
};

return [actionColumn];
}, [input.indexPattern, services, searchQueryLanguage, searchString]);
}, [input.indexPattern, services, searchQueryLanguage, searchString, input.allowEditDataView]);

return {
progress: combinedProgress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -189,6 +198,7 @@ export const IndexDataVisualizer: FC<{ additionalLinks: ResultLink[] }> = ({ add
fileUpload,
lens,
dataViewFieldEditor,
uiActions,
...coreStart,
};

Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/data_visualizer/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -38,6 +39,7 @@ export interface DataVisualizerStartDependencies {
lens?: LensPublicStart;
dataViewFieldEditor?: IndexPatternFieldEditorStart;
fieldFormats: FieldFormatsStart;
uiActions?: UiActionsStart;
}

export type DataVisualizerPluginSetup = ReturnType<DataVisualizerPlugin['setup']>;
Expand Down

0 comments on commit 4af8966

Please sign in to comment.