[Maps] Use field formatter to format value in legend (#48132) (#48254)

* [Maps] Use field formatter to format value in legend

* remove console statement

* simplify logic

* review feed back
This commit is contained in:
Nathan Reese 2019-10-15 12:43:42 -06:00 committed by GitHub
parent 99f884f4f8
commit 7662c6b194
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 112 additions and 9 deletions

View file

@ -49,6 +49,12 @@ export const EMS_FILE = 'EMS_FILE';
export const ES_GEO_GRID = 'ES_GEO_GRID';
export const ES_SEARCH = 'ES_SEARCH';
export const ES_PEW_PEW = 'ES_PEW_PEW';
export const FIELD_ORIGIN = {
SOURCE: 'source',
JOIN: 'join'
};
export const SOURCE_DATA_ID_ORIGIN = 'source';
export const GEOJSON_FILE = 'GEOJSON_FILE';

View file

@ -476,4 +476,9 @@ export class ESSearchSource extends AbstractESSource {
path: geoField.name,
};
}
_getRawFieldName(fieldName) {
// fieldName is rawFieldName for documents source since the source uses raw documents instead of aggregated metrics
return fieldName;
}
}

View file

@ -301,4 +301,33 @@ export class AbstractESSource extends AbstractVectorSource {
return this._descriptor.id;
}
_getRawFieldName(fieldName) {
const metricField = this.getMetricFields().find(({ propertyKey }) => {
return propertyKey === fieldName;
});
return metricField ? metricField.field : null;
}
async getFieldFormatter(fieldName) {
// fieldName could be an aggregation so it needs to be unpacked to expose raw field.
const rawFieldName = this._getRawFieldName(fieldName);
if (!rawFieldName) {
return null;
}
let indexPattern;
try {
indexPattern = await this._getIndexPattern();
} catch(error) {
return null;
}
const fieldFromIndexPattern = indexPattern.fields.byName[rawFieldName];
if (!fieldFromIndexPattern) {
return null;
}
return fieldFromIndexPattern.format.getConverterFor('text');
}
}

View file

@ -127,6 +127,11 @@ export class AbstractSource {
async getPreIndexedShape(/* properties */) {
return null;
}
// Returns function used to format value
async getFieldFormatter(/* fieldName */) {
return null;
}
}

View file

@ -70,19 +70,25 @@ function renderHeaderWithIcons(icons) {
);
}
const EMPTY_VALUE = '';
export class StylePropertyLegendRow extends Component {
state = {
label: '',
hasLoadedFieldFormatter: false,
}
componentDidMount() {
this._isMounted = true;
this._prevLabel = undefined;
this._fieldValueFormatter = undefined;
this._loadLabel();
this._loadFieldFormatter();
}
componentDidUpdate() {
// label could change so it needs to be loaded on update
this._loadLabel();
}
@ -90,6 +96,13 @@ export class StylePropertyLegendRow extends Component {
this._isMounted = false;
}
async _loadFieldFormatter() {
this._fieldValueFormatter = await this.props.getFieldFormatter(this.props.options.field);
if (this._isMounted) {
this.setState({ hasLoadedFieldFormatter: true });
}
}
_loadLabel = async () => {
if (this._isStatic()) {
return;
@ -112,6 +125,14 @@ export class StylePropertyLegendRow extends Component {
!this.props.options.field || !this.props.options.field.name;
}
_formatValue = value => {
if (!this.state.hasLoadedFieldFormatter || !this._fieldValueFormatter || value === EMPTY_VALUE) {
return value;
}
return this._fieldValueFormatter(value);
}
render() {
const { name, options, range } = this.props;
if (this._isStatic()) {
@ -130,8 +151,8 @@ export class StylePropertyLegendRow extends Component {
return (
<StyleLegendRow
header={header}
minLabel={_.get(range, 'min', '')}
maxLabel={_.get(range, 'max', '')}
minLabel={this._formatValue(_.get(range, 'min', EMPTY_VALUE))}
maxLabel={this._formatValue(_.get(range, 'max', EMPTY_VALUE))}
propertyLabel={getVectorStyleLabel(name)}
fieldLabel={this.state.label}
/>
@ -145,4 +166,5 @@ StylePropertyLegendRow.propTypes = {
options: PropTypes.oneOfType(styleOptionShapes).isRequired,
range: rangeShape,
getFieldLabel: PropTypes.func.isRequired,
getFieldFormatter: PropTypes.func.isRequired,
};

View file

@ -10,7 +10,7 @@ import PropTypes from 'prop-types';
import { styleOptionShapes, rangeShape } from '../style_option_shapes';
import { StylePropertyLegendRow } from './style_property_legend_row';
export function VectorStyleLegend({ getFieldLabel, styleProperties }) {
export function VectorStyleLegend({ getFieldLabel, getFieldFormatter, styleProperties }) {
return styleProperties.map(styleProperty => {
return (
<StylePropertyLegendRow
@ -20,6 +20,7 @@ export function VectorStyleLegend({ getFieldLabel, styleProperties }) {
options={styleProperty.options}
range={styleProperty.range}
getFieldLabel={getFieldLabel}
getFieldFormatter={getFieldFormatter}
/>
);
});
@ -34,5 +35,6 @@ const stylePropertyShape = PropTypes.shape({
VectorStyleLegend.propTypes = {
styleProperties: PropTypes.arrayOf(stylePropertyShape).isRequired,
getFieldLabel: PropTypes.func.isRequired
getFieldLabel: PropTypes.func.isRequired,
getFieldFormatter: PropTypes.func.isRequired,
};

View file

@ -303,7 +303,7 @@ export class VectorStyle extends AbstractStyle {
);
}
getLegendDetails(getFieldLabel) {
getLegendDetails(getFieldLabel, getFieldFormatter) {
const styles = this.getProperties();
const styleProperties = Object.keys(styles).map(styleName => {
const { type, options } = styles[styleName];
@ -319,6 +319,7 @@ export class VectorStyle extends AbstractStyle {
<VectorStyleLegend
styleProperties={styleProperties}
getFieldLabel={getFieldLabel}
getFieldFormatter={getFieldFormatter}
/>
);
}

View file

@ -15,7 +15,8 @@ import {
SOURCE_DATA_ID_ORIGIN,
FEATURE_VISIBLE_PROPERTY_NAME,
EMPTY_FEATURE_COLLECTION,
LAYER_TYPE
LAYER_TYPE,
FIELD_ORIGIN,
} from '../../common/constants';
import _ from 'lodash';
import { JoinTooltipProperty } from './tooltips/join_tooltip_property';
@ -202,7 +203,16 @@ export class VectorLayer extends AbstractLayer {
return field ? field.label : fieldName;
};
return this._style.getLegendDetails(getFieldLabel);
const getFieldFormatter = async field => {
const source = this._getFieldSource(field);
if (!source) {
return null;
}
return await source.getFieldFormatter(field.name);
};
return this._style.getLegendDetails(getFieldLabel, getFieldFormatter);
}
_getBoundsBasedOnData() {
@ -249,7 +259,7 @@ export class VectorLayer extends AbstractLayer {
return {
label,
name,
origin: SOURCE_DATA_ID_ORIGIN
origin: FIELD_ORIGIN.SOURCE
};
});
const joinFields = [];
@ -257,7 +267,7 @@ export class VectorLayer extends AbstractLayer {
const fields = join.getJoinFields().map(joinField => {
return {
...joinField,
origin: 'join',
origin: FIELD_ORIGIN.JOIN,
};
});
joinFields.push(...fields);
@ -794,4 +804,27 @@ export class VectorLayer extends AbstractLayer {
});
}
_getFieldSource(field) {
if (!field) {
return null;
}
if (field.origin === FIELD_ORIGIN.SOURCE) {
return this._source;
}
const join = this.getValidJoins().find(join => {
const matchingField = join.getJoinFields().find(joinField => {
return joinField.name === field.name;
});
return !!matchingField;
});
if (!join) {
return null;
}
return join.getRightJoinSource();
}
}