Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] visualize in maps button #98677

Merged
merged 28 commits into from
May 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ebded20
[Lens] visualize in maps button
nreese Apr 28, 2021
ae91101
Merge branch 'master' into lens_link_to_maps
kibanamachine Apr 29, 2021
8762935
clean up dependency injection as suggested
nreese Apr 29, 2021
a707d1b
add custom workspace render for geo fields
nreese Apr 30, 2021
c97fa4b
Merge branch 'master' into lens_link_to_maps
kibanamachine May 3, 2021
1ebfdea
tslint and finish drag and drop for geo field
nreese May 3, 2021
c4fc65c
convert react class to function component
nreese May 3, 2021
76313c5
prevent page reload when clicking visualize in maps button
nreese May 3, 2021
dab538d
filter allFields instead of using condition to populate fieldTypeName…
nreese May 4, 2021
9dd3d02
clean up UI
nreese May 4, 2021
5702835
fix jest test
nreese May 4, 2021
a59bef7
globe illustration
nreese May 4, 2021
c4f9207
Merge branch 'master' into lens_link_to_maps
kibanamachine May 5, 2021
68a3b54
UI cleanup
nreese May 5, 2021
1ecc000
functional test
nreese May 5, 2021
873294c
Update x-pack/plugins/lens/public/editor_frame_service/editor_frame/w…
nreese May 10, 2021
21d16a6
Update x-pack/plugins/lens/public/editor_frame_service/editor_frame/w…
nreese May 10, 2021
5fffe4b
Update x-pack/plugins/lens/public/editor_frame_service/editor_frame/w…
nreese May 10, 2021
05f6b5d
Update x-pack/plugins/lens/public/editor_frame_service/editor_frame/w…
nreese May 10, 2021
db3ba29
Update x-pack/plugins/lens/public/editor_frame_service/editor_frame/w…
nreese May 10, 2021
ae91b07
Update x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx
nreese May 10, 2021
e2f1b3d
Merge branch 'master' into lens_link_to_maps
kibanamachine May 10, 2021
050080b
updated globe svg
nreese May 10, 2021
e5a118a
remove unused
nreese May 10, 2021
6c50c4e
better message for drop zone screen reader
nreese May 10, 2021
73b4549
Update x-pack/plugins/lens/public/editor_frame_service/editor_frame/w…
nreese May 10, 2021
2eb13d5
tslint
nreese May 10, 2021
b6af7e4
Merge branch 'master' into lens_link_to_maps
kibanamachine May 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions x-pack/plugins/lens/public/assets/globe_illustration.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Action } from './state_management';
import { DragContext, DragDropIdentifier } from '../../drag_drop';
import { StateSetter, FramePublicAPI, DatasourceDataPanelProps, Datasource } from '../../types';
import { Query, Filter } from '../../../../../../src/plugins/data/public';
import { UiActionsStart } from '../../../../../../src/plugins/ui_actions/public';

interface DataPanelWrapperProps {
datasourceState: unknown;
Expand All @@ -29,6 +30,7 @@ interface DataPanelWrapperProps {
filters: Filter[];
dropOntoWorkspace: (field: DragDropIdentifier) => void;
hasSuggestionForField: (field: DragDropIdentifier) => boolean;
plugins: { uiActions: UiActionsStart };
}

export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => {
Expand Down Expand Up @@ -56,6 +58,7 @@ export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => {
showNoDataPopover: props.showNoDataPopover,
dropOntoWorkspace: props.dropOntoWorkspace,
hasSuggestionForField: props.hasSuggestionForField,
uiActions: props.plugins.uiActions,
};

const [showDatasourceSwitcher, setDatasourceSwitcher] = useState(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ export function EditorFrame(props: EditorFrameProps) {
showNoDataPopover={props.showNoDataPopover}
dropOntoWorkspace={dropOntoWorkspace}
hasSuggestionForField={hasSuggestionForField}
plugins={props.plugins}
/>
}
configPanel={
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@import '../../../mixins';

.lnsVisualizeGeoFieldWorkspacePanel__dragDrop {
padding: $euiSizeXXL ($euiSizeXL * 2);
border: $euiBorderThin;
border-radius: $euiBorderRadius;

&.lnsDragDrop-isDropTarget {
@include lnsDroppable;
@include lnsDroppableActive;

}

&.lnsDragDrop-isActiveDropTarget {
@include lnsDroppableActiveHover;

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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 React from 'react';
import { EuiPageContentBody, EuiText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import {
UiActionsStart,
VISUALIZE_GEO_FIELD_TRIGGER,
} from '../../../../../../../src/plugins/ui_actions/public';
import { getVisualizeGeoFieldMessage } from '../../../utils';
import { DragDrop } from '../../../drag_drop';
import { GlobeIllustration } from '../../../assets/globe_illustration';
import './geo_field_workspace_panel.scss';

interface Props {
fieldType: string;
fieldName: string;
indexPatternId: string;
uiActions: UiActionsStart;
}

const dragDropIdentifier = {
id: 'lnsGeoFieldWorkspace',
humanData: {
label: i18n.translate('xpack.lens.geoFieldWorkspace.dropZoneLabel', {
defaultMessage: 'drop zone to open in maps',
}),
},
};

const dragDropOrder = [1, 0, 0, 0];

export function GeoFieldWorkspacePanel(props: Props) {
function onDrop() {
props.uiActions.getTrigger(VISUALIZE_GEO_FIELD_TRIGGER).exec({
indexPatternId: props.indexPatternId,
fieldName: props.fieldName,
});
}

return (
<EuiPageContentBody className="lnsWorkspacePanelWrapper__pageContentBody">
<EuiText className="lnsWorkspacePanel__emptyContent" textAlign="center" size="s">
<h2>
<strong>{getVisualizeGeoFieldMessage(props.fieldType)}</strong>
</h2>
<GlobeIllustration aria-hidden={true} className="lnsWorkspacePanel__dropIllustration" />
<DragDrop
className="lnsVisualizeGeoFieldWorkspacePanel__dragDrop"
dataTestSubj="lnsGeoFieldWorkspace"
draggable={false}
dropTypes={['field_add']}
order={dragDropOrder}
value={dragDropIdentifier}
onDrop={onDrop}
>
<p>
<strong>
<FormattedMessage
id="xpack.lens.geoFieldWorkspace.dropMessage"
defaultMessage="Drop field here to open in Maps"
/>
</strong>
</p>
</DragDrop>
</EuiText>
</EuiPageContentBody>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -338,17 +338,22 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({
);
};

return (
<WorkspacePanelWrapper
title={title}
framePublicAPI={framePublicAPI}
dispatch={dispatch}
visualizationState={visualizationState}
visualizationId={activeVisualizationId}
datasourceStates={datasourceStates}
datasourceMap={datasourceMap}
visualizationMap={visualizationMap}
>
const dragDropContext = useContext(DragContext);

const renderDragDrop = () => {
const customWorkspaceRenderer =
activeDatasourceId &&
datasourceMap[activeDatasourceId]?.getCustomWorkspaceRenderer &&
dragDropContext.dragging
? datasourceMap[activeDatasourceId].getCustomWorkspaceRenderer!(
datasourceStates[activeDatasourceId].state,
dragDropContext.dragging
)
: undefined;

return customWorkspaceRenderer ? (
customWorkspaceRenderer()
) : (
<DragDrop
className="lnsWorkspacePanel__dragDrop"
dataTestSubj="lnsWorkspace"
Expand All @@ -363,6 +368,21 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({
{Boolean(suggestionForDraggedField) && expression !== null && renderEmptyWorkspace()}
</EuiPageContentBody>
</DragDrop>
);
};

return (
<WorkspacePanelWrapper
title={title}
framePublicAPI={framePublicAPI}
dispatch={dispatch}
visualizationState={visualizationState}
visualizationId={activeVisualizationId}
datasourceStates={datasourceStates}
datasourceMap={datasourceMap}
visualizationMap={visualizationMap}
>
{renderDragDrop()}
</WorkspacePanelWrapper>
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export interface EditorFrameStartPlugins {
embeddable?: EmbeddableStart;
dashboard?: DashboardStart;
expressions: ExpressionsStart;
uiActions?: UiActionsStart;
uiActions: UiActionsStart;
charts: ChartsPluginSetup;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { documentField } from './document_field';
import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks';
import { indexPatternFieldEditorPluginMock } from '../../../../../src/plugins/index_pattern_field_editor/public/mocks';
import { getFieldByNameFactory } from './pure_helpers';
import { uiActionsPluginMock } from '../../../../../src/plugins/ui_actions/public/mocks';

const fieldsOne = [
{
Expand Down Expand Up @@ -267,6 +268,7 @@ describe('IndexPattern Data Panel', () => {
showNoDataPopover: jest.fn(),
dropOntoWorkspace: jest.fn(),
hasSuggestionForField: jest.fn(() => false),
uiActions: uiActionsPluginMock.createStartContract(),
};
});

Expand Down
14 changes: 13 additions & 1 deletion x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { fieldExists } from './pure_helpers';
import { Loader } from '../loader';
import { esQuery, IIndexPattern } from '../../../../../src/plugins/data/public';
import { IndexPatternFieldEditorStart } from '../../../../../src/plugins/index_pattern_field_editor/public';
import { VISUALIZE_GEO_FIELD_TRIGGER } from '../../../../../src/plugins/ui_actions/public';

export type Props = Omit<DatasourceDataPanelProps<IndexPatternPrivateState>, 'core'> & {
data: DataPublicPluginStart;
Expand Down Expand Up @@ -73,6 +74,8 @@ const supportedFieldTypes = new Set([
'ip_range',
'histogram',
'document',
'geo_point',
'geo_shape',
]);

const fieldTypeNames: Record<DataType, string> = {
Expand All @@ -83,6 +86,8 @@ const fieldTypeNames: Record<DataType, string> = {
date: i18n.translate('xpack.lens.datatypes.date', { defaultMessage: 'date' }),
ip: i18n.translate('xpack.lens.datatypes.ipAddress', { defaultMessage: 'IP' }),
histogram: i18n.translate('xpack.lens.datatypes.histogram', { defaultMessage: 'histogram' }),
geo_point: i18n.translate('xpack.lens.datatypes.geoPoint', { defaultMessage: 'geo_point' }),
geo_shape: i18n.translate('xpack.lens.datatypes.geoShape', { defaultMessage: 'geo_shape' }),
};

// Wrapper around esQuery.buildEsQuery, handling errors (e.g. because a query can't be parsed) by
Expand Down Expand Up @@ -121,6 +126,7 @@ export function IndexPatternDataPanel({
showNoDataPopover,
dropOntoWorkspace,
hasSuggestionForField,
uiActions,
}: Props) {
const { indexPatternRefs, indexPatterns, currentIndexPatternId } = state;
const onChangeIndexPattern = useCallback(
Expand Down Expand Up @@ -233,6 +239,7 @@ export function IndexPatternDataPanel({
existenceFetchTimeout={state.existenceFetchTimeout}
dropOntoWorkspace={dropOntoWorkspace}
hasSuggestionForField={hasSuggestionForField}
uiActions={uiActions}
/>
)}
</>
Expand Down Expand Up @@ -286,6 +293,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
charts,
dropOntoWorkspace,
hasSuggestionForField,
uiActions,
}: Omit<DatasourceDataPanelProps, 'state' | 'setState' | 'showNoDataPopover' | 'core'> & {
data: DataPublicPluginStart;
core: CoreStart;
Expand All @@ -310,7 +318,10 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
isMetaAccordionOpen: false,
});
const currentIndexPattern = indexPatterns[currentIndexPatternId];
const allFields = currentIndexPattern.fields;
const visualizeGeoFieldTrigger = uiActions.getTrigger(VISUALIZE_GEO_FIELD_TRIGGER);
const allFields = visualizeGeoFieldTrigger
? currentIndexPattern.fields
: currentIndexPattern.fields.filter(({ type }) => type !== 'geo_point' && type !== 'geo_shape');
const clearLocalState = () => setLocalState((s) => ({ ...s, nameFilter: '', typeFilter: [] }));
const hasSyncedExistingFields = existingFields[currentIndexPattern.title];
const availableFieldTypes = uniq(allFields.map(({ type }) => type)).filter(
Expand Down Expand Up @@ -807,6 +818,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
hasSuggestionForField={hasSuggestionForField}
editField={editField}
removeField={removeField}
uiActions={uiActions}
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks';
import { IndexPattern } from './types';
import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks';
import { documentField } from './document_field';
import { uiActionsPluginMock } from '../../../../../src/plugins/ui_actions/public/mocks';

const chartsThemeService = chartPluginMock.createSetupContract().theme;

Expand Down Expand Up @@ -109,6 +110,7 @@ describe('IndexPattern Field Item', () => {
itemIndex: 0,
dropOntoWorkspace: () => {},
hasSuggestionForField: () => false,
uiActions: uiActionsPluginMock.createStartContract(),
};

data.fieldFormats = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ import { BucketedAggregation, FieldStatsResponse } from '../../common';
import { IndexPattern, IndexPatternField, DraggedField } from './types';
import { LensFieldIcon } from './lens_field_icon';
import { trackUiEvent } from '../lens_ui_telemetry';
import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public';
import { VisualizeGeoFieldButton } from './visualize_geo_field_button';
import { getVisualizeGeoFieldMessage } from '../utils';

import { debouncedComponent } from '../debounced_component';

Expand All @@ -75,6 +78,7 @@ export interface FieldItemProps {
editField?: (name: string) => void;
removeField?: (name: string) => void;
hasSuggestionForField: DatasourceDataPanelProps['hasSuggestionForField'];
uiActions: UiActionsStart;
}

interface State {
Expand Down Expand Up @@ -149,7 +153,13 @@ export const InnerFieldItem = function InnerFieldItem(props: FieldItemProps) {

function fetchData() {
// Range types don't have any useful stats we can show
if (state.isLoading || field.type === 'document' || field.type.includes('range')) {
if (
state.isLoading ||
field.type === 'document' ||
field.type.includes('range') ||
field.type === 'geo_point' ||
field.type === 'geo_shape'
) {
return;
}

Expand Down Expand Up @@ -392,6 +402,7 @@ function FieldItemPopoverContents(props: State & FieldItemProps) {
removeField,
hasSuggestionForField,
hideDetails,
uiActions,
} = props;

const chartTheme = chartsThemeService.useChartsTheme();
Expand Down Expand Up @@ -467,6 +478,21 @@ function FieldItemPopoverContents(props: State & FieldItemProps) {
</EuiText>
</>
);
} else if (field.type === 'geo_point' || field.type === 'geo_shape') {
return (
<>
<EuiPopoverTitle>{panelHeader}</EuiPopoverTitle>

<EuiText size="s">{getVisualizeGeoFieldMessage(field.type)}</EuiText>

<EuiSpacer size="m" />
<VisualizeGeoFieldButton
uiActions={uiActions}
indexPatternId={indexPattern.id}
fieldName={field.name}
/>
</>
);
} else if (
(!props.histogram || props.histogram.buckets.length === 0) &&
(!props.topValues || props.topValues.buckets.length === 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { NoFieldsCallout } from './no_fields_callout';
import { IndexPatternField } from './types';
import { FieldItemSharedProps, FieldsAccordion } from './fields_accordion';
import { DatasourceDataPanelProps } from '../types';
import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public';
const PAGINATION_SIZE = 50;

export type FieldGroups = Record<
Expand Down Expand Up @@ -55,6 +56,7 @@ export const FieldList = React.memo(function FieldList({
hasSuggestionForField,
editField,
removeField,
uiActions,
}: {
exists: (field: IndexPatternField) => boolean;
fieldGroups: FieldGroups;
Expand All @@ -72,6 +74,7 @@ export const FieldList = React.memo(function FieldList({
hasSuggestionForField: DatasourceDataPanelProps['hasSuggestionForField'];
editField?: (name: string) => void;
removeField?: (name: string) => void;
uiActions: UiActionsStart;
}) {
const [pageSize, setPageSize] = useState(PAGINATION_SIZE);
const [scrollContainer, setScrollContainer] = useState<Element | undefined>(undefined);
Expand Down Expand Up @@ -155,6 +158,7 @@ export const FieldList = React.memo(function FieldList({
groupIndex={0}
dropOntoWorkspace={dropOntoWorkspace}
hasSuggestionForField={hasSuggestionForField}
uiActions={uiActions}
/>
))
)}
Expand Down Expand Up @@ -206,6 +210,7 @@ export const FieldList = React.memo(function FieldList({
defaultNoFieldsMessage={fieldGroup.defaultNoFieldsMessage}
/>
}
uiActions={uiActions}
/>
<EuiSpacer size="m" />
</Fragment>
Expand Down
Loading