Skip to content

Commit

Permalink
Improve field popover
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Roes committed Jun 23, 2021
1 parent 19d2d17 commit 279b72d
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 1,044 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import './discover_field.scss';

import React, { useState, useCallback, memo } from 'react';
import React, { useState, useCallback, memo, useMemo } from 'react';
import {
EuiPopover,
EuiPopoverTitle,
Expand All @@ -18,6 +18,7 @@ import {
EuiIcon,
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { UiCounterMetricType } from '@kbn/analytics';
Expand All @@ -27,7 +28,7 @@ import { FieldIcon, FieldButton } from '../../../../../../../kibana_react/public
import { FieldDetails } from './types';
import { IndexPatternField, IndexPattern } from '../../../../../../../data/public';
import { getFieldTypeName } from './lib/get_field_type_name';
import { DiscoverFieldDetailsFooter } from './discover_field_details_footer';
import { DiscoverFieldVisualize } from './discover_field_visualize';

function wrapOnDot(str?: string) {
// u200B is a non-width white-space character, which allows
Expand Down Expand Up @@ -172,6 +173,7 @@ const MultiFields: React.FC<MultiFieldsProps> = memo(
})}
</h5>
</EuiTitle>
<EuiSpacer size="xs" />
{multiFields.map((entry) => (
<FieldButton
size="s"
Expand Down Expand Up @@ -282,6 +284,8 @@ function DiscoverFieldComponent({
setOpen(!infoIsOpen);
}, [infoIsOpen]);

const rawMultiFields = useMemo(() => multiFields?.map((f) => f.field), [multiFields]);

if (field.type === '_source') {
return (
<FieldButton
Expand Down Expand Up @@ -399,23 +403,24 @@ function DiscoverFieldComponent({
field={field}
details={details}
onAddFilter={onAddFilter}
trackUiMetric={trackUiMetric}
/>
{multiFields && (
<MultiFields
multiFields={multiFields}
alwaysShowActionButton={alwaysShowActionButton}
toggleDisplay={toggleDisplay}
/>
)}
{!details.error && (
<DiscoverFieldDetailsFooter
indexPattern={indexPattern}
field={field}
details={details}
onAddFilter={onAddFilter}
/>
<>
<EuiSpacer size="m" />
<MultiFields
multiFields={multiFields}
alwaysShowActionButton={alwaysShowActionButton}
toggleDisplay={toggleDisplay}
/>
</>
)}
<DiscoverFieldVisualize
field={field}
indexPattern={indexPattern}
multiFields={rawMultiFields}
trackUiMetric={trackUiMetric}
details={details}
/>
</>
)}
</EuiPopover>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,19 @@ const indexPattern = getStubIndexPattern(
);

describe('discover sidebar field details', function () {
const onAddFilter = jest.fn();
const defaultProps = {
indexPattern,
details: { buckets: [], error: '', exists: 1, total: 2, columns: [] },
onAddFilter: jest.fn(),
onAddFilter,
};

function mountComponent(field: IndexPatternField) {
const compProps = { ...defaultProps, field };
return mountWithIntl(<DiscoverFieldDetails {...compProps} />);
}

it('should enable the visualize link for a number field', function () {
it('click on addFilter calls the function', function () {
const visualizableField = new IndexPatternField({
name: 'bytes',
type: 'number',
Expand All @@ -47,37 +48,9 @@ describe('discover sidebar field details', function () {
aggregatable: true,
readFromDocValues: true,
});
const comp = mountComponent(visualizableField);
expect(findTestSubject(comp, 'fieldVisualize-bytes')).toBeTruthy();
});

it('should disable the visualize link for an _id field', function () {
const conflictField = new IndexPatternField({
name: '_id',
type: 'string',
esTypes: ['_id'],
count: 0,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
});
const comp = mountComponent(conflictField);
expect(findTestSubject(comp, 'fieldVisualize-_id')).toEqual({});
});

it('should disable the visualize link for an unknown field', function () {
const unknownField = new IndexPatternField({
name: 'test',
type: 'unknown',
esTypes: ['double'],
count: 0,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
});
const comp = mountComponent(unknownField);
expect(findTestSubject(comp, 'fieldVisualize-test')).toEqual({});
const component = mountComponent(visualizableField);
const onAddButton = findTestSubject(component, 'onAddFilterButton');
onAddButton.simulate('click');
expect(onAddFilter).toHaveBeenCalledWith('_exists_', visualizableField.name, '+');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,105 +6,69 @@
* Side Public License, v 1.
*/

import React, { useState, useEffect } from 'react';
import { EuiIconTip, EuiText, EuiButton, EuiSpacer } from '@elastic/eui';
import React from 'react';
import { EuiText, EuiSpacer, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { METRIC_TYPE, UiCounterMetricType } from '@kbn/analytics';
import { DiscoverFieldBucket } from './discover_field_bucket';
import { getWarnings } from './lib/get_warnings';
import {
triggerVisualizeActions,
isFieldVisualizable,
getVisualizeHref,
} from './lib/visualize_trigger_utils';
import { Bucket, FieldDetails } from './types';
import { IndexPatternField, IndexPattern } from '../../../../../../../data/public';
import './discover_field_details.scss';

interface DiscoverFieldDetailsProps {
field: IndexPatternField;
indexPattern: IndexPattern;
details: FieldDetails;
onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void;
trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void;
}

export function DiscoverFieldDetails({
field,
indexPattern,
details,
onAddFilter,
trackUiMetric,
}: DiscoverFieldDetailsProps) {
const warnings = getWarnings(field);
const [showVisualizeLink, setShowVisualizeLink] = useState<boolean>(false);
const [visualizeLink, setVisualizeLink] = useState<string>('');

useEffect(() => {
isFieldVisualizable(field, indexPattern.id, details.columns).then(
(flag) => {
setShowVisualizeLink(flag);
// get href only if Visualize button is enabled
getVisualizeHref(field, indexPattern.id, details.columns).then(
(uri) => {
if (uri) setVisualizeLink(uri);
},
() => {
setVisualizeLink('');
}
);
},
() => {
setShowVisualizeLink(false);
}
);
}, [field, indexPattern.id, details.columns]);

const handleVisualizeLinkClick = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
// regular link click. let the uiActions code handle the navigation and show popup if needed
event.preventDefault();
if (trackUiMetric) {
trackUiMetric(METRIC_TYPE.CLICK, 'visualize_link_click');
}
triggerVisualizeActions(field, indexPattern.id, details.columns);
};

return (
<>
<div className="dscFieldDetails">
<div className="">
{details.error && <EuiText size="xs">{details.error}</EuiText>}
{!details.error && (
<div style={{ marginTop: '4px' }}>
{details.buckets.map((bucket: Bucket, idx: number) => (
<DiscoverFieldBucket
key={`bucket${idx}`}
bucket={bucket}
field={field}
onAddFilter={onAddFilter}
/>
))}
</div>
)}

{showVisualizeLink && (
<>
<div style={{ marginTop: '4px' }}>
{details.buckets.map((bucket: Bucket, idx: number) => (
<DiscoverFieldBucket
key={`bucket${idx}`}
bucket={bucket}
field={field}
onAddFilter={onAddFilter}
/>
))}
</div>
<EuiSpacer size="xs" />
{/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
<EuiButton
onClick={(e) => handleVisualizeLinkClick(e)}
href={visualizeLink}
size="s"
className="dscFieldDetails__visualizeBtn"
data-test-subj={`fieldVisualize-${field.name}`}
>
<FormattedMessage
id="discover.fieldChooser.detailViews.visualizeLinkText"
defaultMessage="Visualize"
/>
</EuiButton>
{warnings.length > 0 && (
<EuiIconTip type="alert" color="warning" content={warnings.join(' ')} />
)}
<EuiText size="xs">
{!indexPattern.metaFields.includes(field.name) && !field.scripted ? (
<EuiLink
onClick={() => onAddFilter('_exists_', field.name, '+')}
data-test-subj="onAddFilterButton"
>
<FormattedMessage
id="discover.fieldChooser.detailViews.existsInRecordsText"
defaultMessage="Exists in {value} / {totalValue} records"
values={{
value: details.exists,
totalValue: details.total,
}}
/>
</EuiLink>
) : (
<FormattedMessage
id="discover.fieldChooser.detailViews.valueOfRecordsText"
defaultMessage="{value} / {totalValue} records"
values={{
value: details.exists,
totalValue: details.total,
}}
/>
)}
</EuiText>
</>
)}
</div>
Expand Down

This file was deleted.

Loading

0 comments on commit 279b72d

Please sign in to comment.