mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* [FieldIcon] Refactor to extend EuiToken and props * [Add to FieldIcon] Export props * [Graph] Updated instances of FieldIcon * [Maps] Update FieldIcon instance * [Lens] Update FieldIcon usage * [Discover] Update FieldIcon usage * Remove comment * [Lens] Delete unused files * [Graph] Fix alignments * More cleanup * Fixing snaps * [Lens] Removing method `getColorForDataType` The method no longer returns the correct color and EuiProgress doesn’t currently support all the colors from the token map. @cchaos will follow up with a PR to address the coloring of the field data charts. Right now they will fallback to pink for progress and default for charts. * [Maps] Fixing implementations of FieldIcon * [Graph] Using css utility class instead of custom class * Snap * Fix css to use var
This commit is contained in:
parent
31bc4114b1
commit
ee5ebd963a
25 changed files with 426 additions and 339 deletions
|
@ -206,7 +206,7 @@ discover-app {
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
.dscField--noResults {
|
||||
.dscFieldName--noResults {
|
||||
color: $euiColorDarkShade;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,73 +1,109 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FieldName renders a geo field, useShortDots is set to true 1`] = `
|
||||
<span
|
||||
class="dscField--noResults"
|
||||
title="Geo point field"
|
||||
<div
|
||||
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow dscFieldName dscFieldName--noResults"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-label="Geo point field"
|
||||
class="euiIcon euiIcon--small euiIcon-isLoading"
|
||||
focusable="false"
|
||||
height="16"
|
||||
role="img"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
<span
|
||||
class="dscFieldName"
|
||||
<div
|
||||
class="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
t.t.test
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-label="Geo point field"
|
||||
class="euiToken euiToken--euiColorVis5 euiToken--square euiToken--light euiToken--small kbnFieldIcon"
|
||||
title="Geo point field"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="euiIcon euiIcon--medium euiIcon-isLoading"
|
||||
focusable="false"
|
||||
height="16"
|
||||
role="img"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="euiFlexItem eui-textTruncate"
|
||||
>
|
||||
<span
|
||||
class="dscFieldName__displayName eui-textTruncate"
|
||||
>
|
||||
t.t.test
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`FieldName renders a number field by providing a field record, useShortDots is set to false 1`] = `
|
||||
<span
|
||||
class=""
|
||||
title="Number field"
|
||||
<div
|
||||
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow dscFieldName"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-label="Number field"
|
||||
class="euiIcon euiIcon--small euiIcon-isLoading"
|
||||
focusable="false"
|
||||
height="16"
|
||||
role="img"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
<span
|
||||
class="dscFieldName"
|
||||
<div
|
||||
class="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
test.test.test
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-label="Number field"
|
||||
class="euiToken euiToken--euiColorVis0 euiToken--square euiToken--light euiToken--small kbnFieldIcon"
|
||||
title="Number field"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="euiIcon euiIcon--medium euiIcon-isLoading"
|
||||
focusable="false"
|
||||
height="16"
|
||||
role="img"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="euiFlexItem eui-textTruncate"
|
||||
>
|
||||
<span
|
||||
class="dscFieldName__displayName eui-textTruncate"
|
||||
>
|
||||
test.test.test
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`FieldName renders a string field by providing fieldType and fieldName 1`] = `
|
||||
<span
|
||||
class=""
|
||||
title="String field"
|
||||
<div
|
||||
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow dscFieldName"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-label="String field"
|
||||
class="euiIcon euiIcon--small euiIcon-isLoading"
|
||||
focusable="false"
|
||||
height="16"
|
||||
role="img"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
<span
|
||||
class="dscFieldName"
|
||||
<div
|
||||
class="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
test
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-label="String field"
|
||||
class="euiToken euiToken--euiColorVis1 euiToken--square euiToken--light euiToken--small kbnFieldIcon"
|
||||
title="String field"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="euiIcon euiIcon--medium euiIcon-isLoading"
|
||||
focusable="false"
|
||||
height="16"
|
||||
role="img"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="euiFlexItem eui-textTruncate"
|
||||
>
|
||||
<span
|
||||
class="dscFieldName__displayName eui-textTruncate"
|
||||
>
|
||||
test
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { FieldIcon } from '../../../../../../../../../plugins/kibana_react/public';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
||||
import { FieldIcon, FieldIconProps } from '../../../../../../../../../plugins/kibana_react/public';
|
||||
import { shortenDottedString } from '../../../../../../../../../plugins/data/common/utils';
|
||||
import { getFieldTypeName } from './field_type_name';
|
||||
|
||||
|
@ -35,25 +37,35 @@ interface Props {
|
|||
fieldName?: string;
|
||||
fieldType?: string;
|
||||
useShortDots?: boolean;
|
||||
fieldIconProps?: Omit<FieldIconProps, 'type'>;
|
||||
}
|
||||
|
||||
export function FieldName({ field, fieldName, fieldType, useShortDots }: Props) {
|
||||
export function FieldName({ field, fieldName, fieldType, useShortDots, fieldIconProps }: Props) {
|
||||
const type = field ? String(field.type) : String(fieldType);
|
||||
const typeName = getFieldTypeName(type);
|
||||
|
||||
const name = field ? String(field.name) : String(fieldName);
|
||||
const displayName = useShortDots ? shortenDottedString(name) : name;
|
||||
|
||||
const className = classNames({
|
||||
'dscField--noResults': field ? !field.rowCount && !field.scripted : false,
|
||||
// this is currently not styled, should display an icon
|
||||
scripted: field ? field.scripted : false,
|
||||
const noResults = field ? !field.rowCount && !field.scripted : false;
|
||||
|
||||
const className = classNames('dscFieldName', {
|
||||
'dscFieldName--noResults': noResults,
|
||||
});
|
||||
|
||||
return (
|
||||
<span className={className} title={typeName}>
|
||||
<FieldIcon type={type} label={typeName} />
|
||||
<span className="dscFieldName">{displayName}</span>
|
||||
</span>
|
||||
<EuiFlexGroup className={className} alignItems="center" gutterSize="s" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<FieldIcon
|
||||
type={type}
|
||||
label={typeName}
|
||||
scripted={field ? field.scripted : false}
|
||||
{...fieldIconProps}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem className="eui-textTruncate">
|
||||
<span className="dscFieldName__displayName eui-textTruncate">{displayName}</span>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
.dscFieldName {
|
||||
color: $euiColorDarkShade;
|
||||
padding-left: $euiSizeS;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -87,7 +87,12 @@ export function DocViewTableRow({
|
|||
</td>
|
||||
)}
|
||||
<td className="kbnDocViewer__field">
|
||||
<FieldName field={fieldMapping} fieldName={field} fieldType={fieldType} />
|
||||
<FieldName
|
||||
field={fieldMapping}
|
||||
fieldName={field}
|
||||
fieldType={fieldType}
|
||||
fieldIconProps={{ fill: 'none', color: 'gray' }}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
{isCollapsible && (
|
||||
|
|
|
@ -1,37 +1,159 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FieldIcon renders a blackwhite icon for a string 1`] = `
|
||||
<EuiIcon
|
||||
aria-label="string"
|
||||
size="s"
|
||||
type="string"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders a colored icon for a number 1`] = `
|
||||
<EuiIcon
|
||||
exports[`FieldIcon changes fill when scripted is true 1`] = `
|
||||
<EuiToken
|
||||
aria-label="test"
|
||||
color="#54B399"
|
||||
className="kbnFieldIcon"
|
||||
fill="dark"
|
||||
iconType="tokenNumber"
|
||||
size="s"
|
||||
type="number"
|
||||
title="test"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders an icon for an unknown type 1`] = `
|
||||
<EuiIcon
|
||||
<EuiToken
|
||||
aria-label="test"
|
||||
color="#54B399"
|
||||
className="kbnFieldIcon"
|
||||
color="gray"
|
||||
iconType="questionInCircle"
|
||||
size="s"
|
||||
type="questionInCircle"
|
||||
title="test"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types _source is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="_source"
|
||||
className="kbnFieldIcon"
|
||||
color="gray"
|
||||
iconType="editorCodeBlock"
|
||||
size="s"
|
||||
title="_source"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types boolean is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="boolean"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenBoolean"
|
||||
size="s"
|
||||
title="boolean"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types conflict is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="conflict"
|
||||
className="kbnFieldIcon"
|
||||
color="euiVisColor9"
|
||||
iconType="alert"
|
||||
size="s"
|
||||
title="conflict"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types date is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="date"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenDate"
|
||||
size="s"
|
||||
title="date"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types geo_point is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="geo_point"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenGeo"
|
||||
size="s"
|
||||
title="geo_point"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types geo_shape is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="geo_shape"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenGeo"
|
||||
size="s"
|
||||
title="geo_shape"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types ip is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="ip"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenIP"
|
||||
size="s"
|
||||
title="ip"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types murmur3 is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="murmur3"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenFile"
|
||||
size="s"
|
||||
title="murmur3"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types nested is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="nested"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenNested"
|
||||
size="s"
|
||||
title="nested"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types number is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="number"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenNumber"
|
||||
size="s"
|
||||
title="number"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders known field types string is rendered 1`] = `
|
||||
<EuiToken
|
||||
aria-label="string"
|
||||
className="kbnFieldIcon"
|
||||
iconType="tokenString"
|
||||
size="s"
|
||||
title="string"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon renders with className if provided 1`] = `
|
||||
<EuiIcon
|
||||
<EuiToken
|
||||
aria-label="test"
|
||||
className="myClass"
|
||||
color="#54B399"
|
||||
className="kbnFieldIcon myClass"
|
||||
color="gray"
|
||||
iconType="questionInCircle"
|
||||
size="s"
|
||||
type="questionInCircle"
|
||||
title="test"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FieldIcon supports same props as EuiToken 1`] = `
|
||||
<EuiToken
|
||||
aria-label="test"
|
||||
className="kbnFieldIcon"
|
||||
color="euiColorVis0"
|
||||
fill="none"
|
||||
iconType="tokenNumber"
|
||||
shape="circle"
|
||||
size="l"
|
||||
title="test"
|
||||
/>
|
||||
`;
|
||||
|
|
|
@ -18,24 +18,44 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { FieldIcon } from './field_icon';
|
||||
import { FieldIcon, typeToEuiIconMap } from './field_icon';
|
||||
|
||||
test('FieldIcon renders a blackwhite icon for a string', () => {
|
||||
const component = shallow(<FieldIcon type="string" />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
const availableTypes = Object.keys(typeToEuiIconMap);
|
||||
|
||||
test('FieldIcon renders a colored icon for a number', () => {
|
||||
const component = shallow(<FieldIcon type="number" label="test" useColor />);
|
||||
expect(component).toMatchSnapshot();
|
||||
describe('FieldIcon renders known field types', () => {
|
||||
availableTypes.forEach(type => {
|
||||
test(`${type} is rendered`, () => {
|
||||
const component = shallow(<FieldIcon type={type} />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('FieldIcon renders an icon for an unknown type', () => {
|
||||
const component = shallow(<FieldIcon type="sdfsdf" label="test" useColor />);
|
||||
const component = shallow(<FieldIcon type="sdfsdf" label="test" />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('FieldIcon supports same props as EuiToken', () => {
|
||||
const component = shallow(
|
||||
<FieldIcon
|
||||
type="number"
|
||||
label="test"
|
||||
color="euiColorVis0"
|
||||
size="l"
|
||||
shape="circle"
|
||||
fill="none"
|
||||
/>
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('FieldIcon changes fill when scripted is true', () => {
|
||||
const component = shallow(<FieldIcon type="number" label="test" scripted={true} />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('FieldIcon renders with className if provided', () => {
|
||||
const component = shallow(<FieldIcon type="sdfsdf" label="test" className="myClass" useColor />);
|
||||
const component = shallow(<FieldIcon type="sdfsdf" label="test" className="myClass" />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -17,14 +17,10 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { euiPaletteColorBlind, EuiIcon } from '@elastic/eui';
|
||||
import { IconSize } from '@elastic/eui/src/components/icon/icon';
|
||||
import classNames from 'classnames';
|
||||
import { EuiToken, EuiTokenProps } from '@elastic/eui';
|
||||
|
||||
interface IconMapEntry {
|
||||
icon: string;
|
||||
color: string;
|
||||
}
|
||||
interface FieldIconProps {
|
||||
export interface FieldIconProps extends Omit<EuiTokenProps, 'iconType'> {
|
||||
type:
|
||||
| 'boolean'
|
||||
| 'conflict'
|
||||
|
@ -39,51 +35,50 @@ interface FieldIconProps {
|
|||
| string
|
||||
| 'nested';
|
||||
label?: string;
|
||||
size?: IconSize;
|
||||
useColor?: boolean;
|
||||
className?: string;
|
||||
scripted?: boolean;
|
||||
}
|
||||
|
||||
const colors = euiPaletteColorBlind();
|
||||
|
||||
// defaultIcon => a unknown datatype
|
||||
const defaultIcon = { icon: 'questionInCircle', color: colors[0] };
|
||||
const defaultIcon = { iconType: 'questionInCircle', color: 'gray' };
|
||||
|
||||
export const typeToEuiIconMap: Partial<Record<string, IconMapEntry>> = {
|
||||
boolean: { icon: 'invert', color: colors[5] },
|
||||
export const typeToEuiIconMap: Partial<Record<string, EuiTokenProps>> = {
|
||||
boolean: { iconType: 'tokenBoolean' },
|
||||
// icon for an index pattern mapping conflict in discover
|
||||
conflict: { icon: 'alert', color: colors[8] },
|
||||
date: { icon: 'calendar', color: colors[7] },
|
||||
geo_point: { icon: 'globe', color: colors[2] },
|
||||
geo_shape: { icon: 'globe', color: colors[2] },
|
||||
ip: { icon: 'storage', color: colors[8] },
|
||||
conflict: { iconType: 'alert', color: 'euiVisColor9' },
|
||||
date: { iconType: 'tokenDate' },
|
||||
geo_point: { iconType: 'tokenGeo' },
|
||||
geo_shape: { iconType: 'tokenGeo' },
|
||||
ip: { iconType: 'tokenIP' },
|
||||
// is a plugin's data type https://www.elastic.co/guide/en/elasticsearch/plugins/current/mapper-murmur3-usage.html
|
||||
murmur3: { icon: 'document', color: colors[1] },
|
||||
number: { icon: 'number', color: colors[0] },
|
||||
_source: { icon: 'editorCodeBlock', color: colors[3] },
|
||||
string: { icon: 'string', color: colors[4] },
|
||||
nested: { icon: 'nested', color: colors[2] },
|
||||
murmur3: { iconType: 'tokenFile' },
|
||||
number: { iconType: 'tokenNumber' },
|
||||
_source: { iconType: 'editorCodeBlock', color: 'gray' },
|
||||
string: { iconType: 'tokenString' },
|
||||
nested: { iconType: 'tokenNested' },
|
||||
};
|
||||
|
||||
/**
|
||||
* Field icon used across the app
|
||||
* Field token icon used across the app
|
||||
*/
|
||||
export function FieldIcon({
|
||||
type,
|
||||
label,
|
||||
size = 's',
|
||||
useColor = false,
|
||||
className = undefined,
|
||||
scripted,
|
||||
className,
|
||||
...rest
|
||||
}: FieldIconProps) {
|
||||
const euiIcon = typeToEuiIconMap[type] || defaultIcon;
|
||||
const token = typeToEuiIconMap[type] || defaultIcon;
|
||||
|
||||
return (
|
||||
<EuiIcon
|
||||
type={euiIcon.icon}
|
||||
<EuiToken
|
||||
{...token}
|
||||
className={classNames('kbnFieldIcon', className)}
|
||||
aria-label={label || type}
|
||||
size={size as IconSize}
|
||||
color={useColor || type === 'conflict' ? euiIcon.color : undefined}
|
||||
className={className}
|
||||
title={label || type}
|
||||
size={size as EuiTokenProps['size']}
|
||||
fill={scripted ? 'dark' : undefined}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -237,10 +237,18 @@ export function FieldEditor({
|
|||
renderOption={(option, searchValue, contentClassName) => {
|
||||
const { type, label } = option;
|
||||
return (
|
||||
<span className={contentClassName}>
|
||||
<FieldIcon type={type!} size="m" useColor />{' '}
|
||||
<EuiHighlight search={searchValue}>{label}</EuiHighlight>
|
||||
</span>
|
||||
<EuiFlexGroup
|
||||
className={contentClassName}
|
||||
gutterSize="s"
|
||||
alignItems="center"
|
||||
>
|
||||
<EuiFlexItem grow={null}>
|
||||
<FieldIcon type={type!} fill="none" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiHighlight search={searchValue}>{label}</EuiHighlight>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}}
|
||||
compressed
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ICON_TYPES, euiPaletteColorBlind, EuiIcon } from '@elastic/eui';
|
||||
|
||||
function stringToNum(s: string) {
|
||||
return Array.from(s).reduce((acc, ch) => acc + ch.charCodeAt(0), 1);
|
||||
}
|
||||
|
||||
function getIconForDataType(dataType: string) {
|
||||
const icons: Partial<Record<string, UnwrapArray<typeof ICON_TYPES>>> = {
|
||||
boolean: 'invert',
|
||||
date: 'calendar',
|
||||
geo_point: 'globe',
|
||||
ip: 'storage',
|
||||
};
|
||||
return icons[dataType] || ICON_TYPES.find(t => t === dataType) || 'document';
|
||||
}
|
||||
|
||||
export function getColorForDataType(type: string) {
|
||||
const iconType = getIconForDataType(type);
|
||||
const colors = euiPaletteColorBlind();
|
||||
const colorIndex = stringToNum(iconType) % colors.length;
|
||||
return colors[colorIndex];
|
||||
}
|
||||
|
||||
export type UnwrapArray<T> = T extends Array<infer P> ? P : T;
|
||||
|
||||
export function FieldIcon({ type }: { type: string }) {
|
||||
const iconType = getIconForDataType(type);
|
||||
|
||||
return <EuiIcon type={iconType} color={getColorForDataType(type)} />;
|
||||
}
|
|
@ -122,7 +122,7 @@ function toOptions(
|
|||
.filter(field => isExplorable(field) || field.selected)
|
||||
.map(field => ({
|
||||
label: field.name,
|
||||
prepend: <FieldIcon type={field.type} size="m" useColor />,
|
||||
prepend: <FieldIcon className="eui-alignMiddle" type={field.type} fill="none" />,
|
||||
checked: field.selected ? 'on' : undefined,
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`LensFieldIcon accepts FieldIcon props 1`] = `
|
||||
<FieldIcon
|
||||
className="lnsFieldListPanel__fieldIcon"
|
||||
fill="none"
|
||||
type="date"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`LensFieldIcon renders properly 1`] = `
|
||||
<FieldIcon
|
||||
className="lnsFieldListPanel__fieldIcon"
|
||||
size="m"
|
||||
type="date"
|
||||
useColor={true}
|
||||
/>
|
||||
`;
|
||||
|
|
|
@ -52,3 +52,16 @@
|
|||
@include euiFormControlLayoutPadding(1, 'right');
|
||||
@include euiFormControlLayoutPadding(1, 'left');
|
||||
}
|
||||
|
||||
.lnsInnerIndexPatternDataPanel__filterType {
|
||||
padding: $euiSizeS;
|
||||
}
|
||||
|
||||
.lnsInnerIndexPatternDataPanel__filterTypeInner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.lnsFieldListPanel__fieldIcon {
|
||||
margin-right: $euiSizeS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
}
|
||||
|
||||
.lnsFieldItem--missing {
|
||||
background: lightOrDarkTheme(transparentize($euiColorMediumShade, .9), $euiColorEmptyShade);
|
||||
background: lightOrDarkTheme(transparentize($euiColorMediumShade, 0.9), $euiColorEmptyShade);
|
||||
color: $euiColorDarkShade;
|
||||
}
|
||||
|
||||
|
@ -24,10 +24,10 @@
|
|||
display: flex;
|
||||
align-items: flex-start;
|
||||
transition: box-shadow $euiAnimSpeedFast $euiAnimSlightResistance,
|
||||
background-color $euiAnimSpeedFast $euiAnimSlightResistance; // sass-lint:disable-line indentation
|
||||
background-color $euiAnimSpeedFast $euiAnimSlightResistance; // sass-lint:disable-line indentation
|
||||
|
||||
.lnsFieldItem__name {
|
||||
margin-left: $euiSizeXS;
|
||||
margin-left: $euiSizeS;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,8 @@
|
|||
}
|
||||
|
||||
.lnsFieldListPanel__fieldIcon {
|
||||
margin-top: 2px;
|
||||
margin-top: $euiSizeXS / 2;
|
||||
margin-right: $euiSizeXS / 2;
|
||||
}
|
||||
|
||||
.lnsFieldItem__infoIcon {
|
||||
|
|
|
@ -384,6 +384,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
|
|||
data-test-subj="lnsIndexPatternTypeFilterOptions"
|
||||
items={(availableFieldTypes as DataType[]).map(type => (
|
||||
<EuiContextMenuItem
|
||||
className="lnsInnerIndexPatternDataPanel__filterType"
|
||||
key={type}
|
||||
icon={localState.typeFilter.includes(type) ? 'check' : 'empty'}
|
||||
data-test-subj={`typeFilter-${type}`}
|
||||
|
@ -397,7 +398,9 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
|
|||
}));
|
||||
}}
|
||||
>
|
||||
<LensFieldIcon type={type} /> {fieldTypeNames[type]}
|
||||
<span className="lnsInnerIndexPatternDataPanel__filterTypeInner">
|
||||
<LensFieldIcon type={type} /> {fieldTypeNames[type]}
|
||||
</span>
|
||||
</EuiContextMenuItem>
|
||||
))}
|
||||
/>
|
||||
|
|
|
@ -169,6 +169,7 @@ export function FieldSelect({
|
|||
<EuiFlexItem grow={null}>
|
||||
<LensFieldIcon
|
||||
type={((option.value as unknown) as { dataType: DataType }).dataType}
|
||||
fill="none"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { FieldIcon } from './field_icon';
|
||||
|
||||
describe('FieldIcon', () => {
|
||||
it('should render icons', () => {
|
||||
expect(shallow(<FieldIcon type="boolean" />)).toMatchInlineSnapshot(`
|
||||
<EuiIcon
|
||||
className="lnsFieldListPanel__fieldIcon lnsFieldListPanel__fieldIcon--boolean"
|
||||
color="#D6BF57"
|
||||
type="invert"
|
||||
/>
|
||||
`);
|
||||
expect(shallow(<FieldIcon type="date" />)).toMatchInlineSnapshot(`
|
||||
<EuiIcon
|
||||
className="lnsFieldListPanel__fieldIcon lnsFieldListPanel__fieldIcon--date"
|
||||
color="#DA8B45"
|
||||
type="calendar"
|
||||
/>
|
||||
`);
|
||||
expect(shallow(<FieldIcon type="number" />)).toMatchInlineSnapshot(`
|
||||
<EuiIcon
|
||||
className="lnsFieldListPanel__fieldIcon lnsFieldListPanel__fieldIcon--number"
|
||||
color="#54B399"
|
||||
type="number"
|
||||
/>
|
||||
`);
|
||||
expect(shallow(<FieldIcon type="string" />)).toMatchInlineSnapshot(`
|
||||
<EuiIcon
|
||||
className="lnsFieldListPanel__fieldIcon lnsFieldListPanel__fieldIcon--string"
|
||||
color="#CA8EAE"
|
||||
type="string"
|
||||
/>
|
||||
`);
|
||||
expect(shallow(<FieldIcon type="ip" />)).toMatchInlineSnapshot(`
|
||||
<EuiIcon
|
||||
className="lnsFieldListPanel__fieldIcon lnsFieldListPanel__fieldIcon--ip"
|
||||
color="#AA6556"
|
||||
type="ip"
|
||||
/>
|
||||
`);
|
||||
});
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ICON_TYPES, euiPaletteColorBlind, EuiIcon } from '@elastic/eui';
|
||||
import classNames from 'classnames';
|
||||
import { DataType } from '../types';
|
||||
|
||||
function stringToNum(s: string) {
|
||||
return Array.from(s).reduce((acc, ch) => acc + ch.charCodeAt(0), 1);
|
||||
}
|
||||
|
||||
function getIconForDataType(dataType: string) {
|
||||
const icons: Partial<Record<string, UnwrapArray<typeof ICON_TYPES>>> = {
|
||||
boolean: 'invert',
|
||||
date: 'calendar',
|
||||
ip: 'ip',
|
||||
};
|
||||
return icons[dataType] || ICON_TYPES.find(t => t === dataType) || 'empty';
|
||||
}
|
||||
|
||||
export function getColorForDataType(type: string) {
|
||||
const iconType = getIconForDataType(type);
|
||||
const colors = euiPaletteColorBlind();
|
||||
const colorIndex = stringToNum(iconType) % colors.length;
|
||||
return colors[colorIndex];
|
||||
}
|
||||
|
||||
export type UnwrapArray<T> = T extends Array<infer P> ? P : T;
|
||||
|
||||
export function FieldIcon({ type }: { type: DataType }) {
|
||||
const iconType = getIconForDataType(type);
|
||||
|
||||
const classes = classNames(
|
||||
'lnsFieldListPanel__fieldIcon',
|
||||
`lnsFieldListPanel__fieldIcon--${type}`
|
||||
);
|
||||
|
||||
return <EuiIcon type={iconType} color={getColorForDataType(type)} className={classes} />;
|
||||
}
|
|
@ -46,7 +46,7 @@ import { DragDrop } from '../drag_drop';
|
|||
import { DatasourceDataPanelProps, DataType } from '../types';
|
||||
import { BucketedAggregation, FieldStatsResponse } from '../../../../../plugins/lens/common';
|
||||
import { IndexPattern, IndexPatternField } from './types';
|
||||
import { getColorForDataType, LensFieldIcon } from './lens_field_icon';
|
||||
import { LensFieldIcon } from './lens_field_icon';
|
||||
import { trackUiEvent } from '../lens_ui_telemetry';
|
||||
|
||||
export interface FieldItemProps {
|
||||
|
@ -294,11 +294,6 @@ function FieldItemPopoverContents(props: State & FieldItemProps) {
|
|||
);
|
||||
}
|
||||
|
||||
const euiButtonColor =
|
||||
field.type === 'string' ? 'accent' : field.type === 'number' ? 'secondary' : 'primary';
|
||||
const euiTextColor =
|
||||
field.type === 'string' ? 'accent' : field.type === 'number' ? 'secondary' : 'default';
|
||||
|
||||
const fromDate = DateMath.parse(dateRange.fromDate);
|
||||
const toDate = DateMath.parse(dateRange.toDate);
|
||||
|
||||
|
@ -391,8 +386,6 @@ function FieldItemPopoverContents(props: State & FieldItemProps) {
|
|||
const specId = i18n.translate('xpack.lens.indexPattern.fieldStatsCountLabel', {
|
||||
defaultMessage: 'Count',
|
||||
});
|
||||
const expectedColor = getColorForDataType(field.type);
|
||||
const seriesColors = expectedColor ? [expectedColor] : undefined;
|
||||
|
||||
if (field.type === 'date') {
|
||||
return wrapInPopover(
|
||||
|
@ -429,7 +422,6 @@ function FieldItemPopoverContents(props: State & FieldItemProps) {
|
|||
yAccessors={['count']}
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
customSeriesColors={seriesColors}
|
||||
timeZone="local"
|
||||
/>
|
||||
</Chart>
|
||||
|
@ -453,7 +445,6 @@ function FieldItemPopoverContents(props: State & FieldItemProps) {
|
|||
yAccessors={['count']}
|
||||
xScaleType={ScaleType.Linear}
|
||||
yScaleType={ScaleType.Linear}
|
||||
customSeriesColors={seriesColors}
|
||||
/>
|
||||
</Chart>
|
||||
);
|
||||
|
@ -486,7 +477,7 @@ function FieldItemPopoverContents(props: State & FieldItemProps) {
|
|||
)}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="xs" textAlign="left" color={euiTextColor}>
|
||||
<EuiText size="xs" textAlign="left" color="accent">
|
||||
{Math.round((topValue.count / props.sampledValues!) * 100)}%
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
@ -497,7 +488,7 @@ function FieldItemPopoverContents(props: State & FieldItemProps) {
|
|||
value={topValue.count / props.sampledValues!}
|
||||
max={1}
|
||||
size="s"
|
||||
color={euiButtonColor}
|
||||
color="accent"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -11,19 +11,14 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { LensFieldIcon, getColorForDataType } from './lens_field_icon';
|
||||
import { LensFieldIcon } from './lens_field_icon';
|
||||
|
||||
test('LensFieldIcon renders properly', () => {
|
||||
const component = shallow(<LensFieldIcon type={'date'} />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('LensFieldIcon getColorForDataType for a valid type', () => {
|
||||
const color = getColorForDataType('date');
|
||||
expect(color).toEqual('#DA8B45');
|
||||
});
|
||||
|
||||
test('LensFieldIcon getColorForDataType for an invalid type', () => {
|
||||
const color = getColorForDataType('invalid');
|
||||
expect(color).toEqual('#54B399');
|
||||
test('LensFieldIcon accepts FieldIcon props', () => {
|
||||
const component = shallow(<LensFieldIcon type={'date'} fill={'none'} />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -5,26 +5,16 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { euiPaletteColorBlind } from '@elastic/eui';
|
||||
import { FieldIcon, typeToEuiIconMap } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import { FieldIcon, FieldIconProps } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import { DataType } from '../types';
|
||||
import { normalizeOperationDataType } from './utils';
|
||||
|
||||
export function getColorForDataType(type: string) {
|
||||
const iconMap = typeToEuiIconMap[normalizeOperationDataType(type as DataType)];
|
||||
if (iconMap) {
|
||||
return iconMap.color;
|
||||
}
|
||||
return euiPaletteColorBlind()[0];
|
||||
}
|
||||
|
||||
export function LensFieldIcon({ type }: { type: DataType }) {
|
||||
export function LensFieldIcon({ type, ...rest }: FieldIconProps & { type: DataType }) {
|
||||
return (
|
||||
<FieldIcon
|
||||
type={normalizeOperationDataType(type)}
|
||||
className="lnsFieldListPanel__fieldIcon"
|
||||
size="m"
|
||||
useColor
|
||||
type={normalizeOperationDataType(type)}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ exports[`Should remove selected fields from selectable 1`] = `
|
|||
id="addTooltipFieldPopover"
|
||||
isOpen={false}
|
||||
ownFocus={true}
|
||||
panelPaddingSize="m"
|
||||
panelPaddingSize="none"
|
||||
>
|
||||
<EuiSelectable
|
||||
onChange={[Function]}
|
||||
|
@ -32,14 +32,19 @@ exports[`Should remove selected fields from selectable 1`] = `
|
|||
Object {
|
||||
"label": "@timestamp",
|
||||
"prepend": <FieldIcon
|
||||
size="m"
|
||||
className="eui-alignMiddle"
|
||||
fill="none"
|
||||
type="date"
|
||||
useColor={true}
|
||||
/>,
|
||||
"value": "@timestamp",
|
||||
},
|
||||
]
|
||||
}
|
||||
searchProps={
|
||||
Object {
|
||||
"compressed": true,
|
||||
}
|
||||
}
|
||||
searchable={true}
|
||||
singleSelection={false}
|
||||
>
|
||||
|
@ -88,7 +93,7 @@ exports[`Should render 1`] = `
|
|||
id="addTooltipFieldPopover"
|
||||
isOpen={false}
|
||||
ownFocus={true}
|
||||
panelPaddingSize="m"
|
||||
panelPaddingSize="none"
|
||||
>
|
||||
<EuiSelectable
|
||||
onChange={[Function]}
|
||||
|
@ -97,32 +102,37 @@ exports[`Should render 1`] = `
|
|||
Object {
|
||||
"label": "@timestamp",
|
||||
"prepend": <FieldIcon
|
||||
size="m"
|
||||
className="eui-alignMiddle"
|
||||
fill="none"
|
||||
type="date"
|
||||
useColor={true}
|
||||
/>,
|
||||
"value": "@timestamp",
|
||||
},
|
||||
Object {
|
||||
"label": "custom label for prop1",
|
||||
"prepend": <FieldIcon
|
||||
size="m"
|
||||
className="eui-alignMiddle"
|
||||
fill="none"
|
||||
type="string"
|
||||
useColor={true}
|
||||
/>,
|
||||
"value": "prop1",
|
||||
},
|
||||
Object {
|
||||
"label": "prop2",
|
||||
"prepend": <FieldIcon
|
||||
size="m"
|
||||
className="eui-alignMiddle"
|
||||
fill="none"
|
||||
type="string"
|
||||
useColor={true}
|
||||
/>,
|
||||
"value": "prop2",
|
||||
},
|
||||
]
|
||||
}
|
||||
searchProps={
|
||||
Object {
|
||||
"compressed": true,
|
||||
}
|
||||
}
|
||||
searchable={true}
|
||||
singleSelection={false}
|
||||
>
|
||||
|
|
|
@ -39,7 +39,10 @@ function getOptions(fields, selectedFields) {
|
|||
.map(field => {
|
||||
return {
|
||||
value: field.name,
|
||||
prepend: 'type' in field ? <FieldIcon type={field.type} size="m" useColor /> : null,
|
||||
prepend:
|
||||
'type' in field ? (
|
||||
<FieldIcon className="eui-alignMiddle" type={field.type} fill="none" />
|
||||
) : null,
|
||||
label: 'label' in field ? field.label : field.name,
|
||||
};
|
||||
})
|
||||
|
@ -127,7 +130,12 @@ export class AddTooltipFieldPopover extends Component {
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiSelectable searchable options={this.state.options} onChange={this._onSelect}>
|
||||
<EuiSelectable
|
||||
searchable
|
||||
searchProps={{ compressed: true }}
|
||||
options={this.state.options}
|
||||
onChange={this._onSelect}
|
||||
>
|
||||
{(list, search) => (
|
||||
<div style={{ width: '300px' }}>
|
||||
<EuiPopoverTitle>{search}</EuiPopoverTitle>
|
||||
|
@ -161,6 +169,7 @@ export class AddTooltipFieldPopover extends Component {
|
|||
button={this._renderAddButton()}
|
||||
isOpen={this.state.isPopoverOpen}
|
||||
closePopover={this._closePopover}
|
||||
panelPaddingSize="none"
|
||||
ownFocus
|
||||
>
|
||||
{this._renderContent()}
|
||||
|
|
|
@ -8,7 +8,7 @@ import _ from 'lodash';
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
import { EuiComboBox, EuiHighlight } from '@elastic/eui';
|
||||
import { EuiComboBox, EuiHighlight, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { FieldIcon } from '../../../../../../src/plugins/kibana_react/public';
|
||||
|
||||
function fieldsToOptions(fields) {
|
||||
|
@ -30,11 +30,14 @@ function fieldsToOptions(fields) {
|
|||
|
||||
function renderOption(option, searchValue, contentClassName) {
|
||||
return (
|
||||
<span className={contentClassName}>
|
||||
<FieldIcon type={option.value.type} size="m" useColor />
|
||||
|
||||
<EuiHighlight search={searchValue}>{option.label}</EuiHighlight>
|
||||
</span>
|
||||
<EuiFlexGroup className={contentClassName} gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={null}>
|
||||
<FieldIcon type={option.value.type} fill="none" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiHighlight search={searchValue}>{option.label}</EuiHighlight>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,18 +7,21 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
import { EuiComboBox, EuiHighlight } from '@elastic/eui';
|
||||
import { EuiComboBox, EuiHighlight, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { FIELD_ORIGIN } from '../../../../../common/constants';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FieldIcon } from '../../../../../../../../../src/plugins/kibana_react/public';
|
||||
|
||||
function renderOption(option, searchValue, contentClassName) {
|
||||
return (
|
||||
<span className={contentClassName}>
|
||||
<FieldIcon type={option.value.type} size="m" useColor />
|
||||
|
||||
<EuiHighlight search={searchValue}>{option.label}</EuiHighlight>
|
||||
</span>
|
||||
<EuiFlexGroup className={contentClassName} gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={null}>
|
||||
<FieldIcon type={option.value.type} fill="none" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiHighlight search={searchValue}>{option.label}</EuiHighlight>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue