fix(scatter): fix legend and labels (#43)

This commit is contained in:
Ville Brofeldt 2021-08-19 17:47:39 +03:00 committed by Yongjie Zhao
parent 55b3c7933d
commit c3e5edf7cf
6 changed files with 50 additions and 43 deletions

View File

@ -58,16 +58,17 @@ function getCategories(fd, data) {
} }
const propTypes = { const propTypes = {
datasource: PropTypes.object.isRequired,
formData: PropTypes.object.isRequired, formData: PropTypes.object.isRequired,
mapboxApiKey: PropTypes.string.isRequired,
setControlValue: PropTypes.func.isRequired,
viewport: PropTypes.object.isRequired,
getLayer: PropTypes.func.isRequired, getLayer: PropTypes.func.isRequired,
getPoints: PropTypes.func.isRequired, getPoints: PropTypes.func.isRequired,
payload: PropTypes.object.isRequired,
onAddFilter: PropTypes.func,
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired, height: PropTypes.number.isRequired,
mapboxApiKey: PropTypes.string.isRequired,
onAddFilter: PropTypes.func,
payload: PropTypes.object.isRequired,
setControlValue: PropTypes.func.isRequired,
viewport: PropTypes.object.isRequired,
width: PropTypes.number.isRequired,
}; };
export default class CategoricalDeckGLContainer extends React.PureComponent { export default class CategoricalDeckGLContainer extends React.PureComponent {
@ -179,7 +180,7 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
data: { ...payload.data, features }, data: { ...payload.data, features },
}; };
return [getLayer(fd, filteredPayload, onAddFilter, this.setTooltip)]; return [getLayer(fd, filteredPayload, onAddFilter, this.setTooltip, this.props.datasource)];
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
@ -255,11 +256,12 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
height={this.props.height} height={this.props.height}
> >
<Legend <Legend
forceCategorical
categories={this.state.categories} categories={this.state.categories}
toggleCategory={this.toggleCategory}
showSingleCategory={this.showSingleCategory}
position={this.props.formData.legend_position}
format={this.props.formData.legend_format} format={this.props.formData.legend_format}
position={this.props.formData.legend_position}
showSingleCategory={this.showSingleCategory}
toggleCategory={this.toggleCategory}
/> />
</AnimatableDeckGLContainer> </AnimatableDeckGLContainer>
</div> </div>

View File

@ -29,23 +29,25 @@ const categoryDelimiter = ' - ';
const propTypes = { const propTypes = {
categories: PropTypes.object, categories: PropTypes.object,
toggleCategory: PropTypes.func, forceCategorical: PropTypes.bool,
showSingleCategory: PropTypes.func,
format: PropTypes.string, format: PropTypes.string,
position: PropTypes.oneOf([null, 'tl', 'tr', 'bl', 'br']), position: PropTypes.oneOf([null, 'tl', 'tr', 'bl', 'br']),
showSingleCategory: PropTypes.func,
toggleCategory: PropTypes.func,
}; };
const defaultProps = { const defaultProps = {
categories: {}, categories: {},
toggleCategory: () => {}, forceCategorical: false,
showSingleCategory: () => {},
format: null, format: null,
position: 'tr', position: 'tr',
showSingleCategory: () => {},
toggleCategory: () => {},
}; };
export default class Legend extends React.PureComponent { export default class Legend extends React.PureComponent {
format(value) { format(value) {
if (!this.props.format) { if (!this.props.format || this.props.forceCategorical) {
return value; return value;
} }

View File

@ -30,13 +30,14 @@ import CategoricalDeckGLContainer from './CategoricalDeckGLContainer';
import fitViewport from './utils/fitViewport'; import fitViewport from './utils/fitViewport';
const propTypes = { const propTypes = {
datasource: PropTypes.object.isRequired,
formData: PropTypes.object.isRequired, formData: PropTypes.object.isRequired,
height: PropTypes.number.isRequired,
onAddFilter: PropTypes.func,
payload: PropTypes.object.isRequired, payload: PropTypes.object.isRequired,
setControlValue: PropTypes.func.isRequired, setControlValue: PropTypes.func.isRequired,
viewport: PropTypes.object.isRequired, viewport: PropTypes.object.isRequired,
onAddFilter: PropTypes.func,
width: PropTypes.number.isRequired, width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
}; };
const defaultProps = { const defaultProps = {
onAddFilter() {}, onAddFilter() {},
@ -120,10 +121,11 @@ export function createDeckGLComponent(getLayer, getPoints) {
export function createCategoricalDeckGLComponent(getLayer, getPoints) { export function createCategoricalDeckGLComponent(getLayer, getPoints) {
function Component(props) { function Component(props) {
const { formData, payload, setControlValue, viewport, width, height } = props; const { datasource, formData, height, payload, setControlValue, viewport, width } = props;
return ( return (
<CategoricalDeckGLContainer <CategoricalDeckGLContainer
datasource={datasource}
formData={formData} formData={formData}
mapboxApiKey={payload.data.mapboxApiKey} mapboxApiKey={payload.data.mapboxApiKey}
setControlValue={setControlValue} setControlValue={setControlValue}

View File

@ -18,7 +18,7 @@
*/ */
import { ScatterplotLayer } from 'deck.gl'; import { ScatterplotLayer } from 'deck.gl';
import React from 'react'; import React from 'react';
import { t } from '@superset-ui/core'; import { getMetricLabel, t } from '@superset-ui/core';
import { commonLayerProps } from '../common'; import { commonLayerProps } from '../common';
import { createCategoricalDeckGLComponent } from '../../factory'; import { createCategoricalDeckGLComponent } from '../../factory';
import TooltipRow from '../../TooltipRow'; import TooltipRow from '../../TooltipRow';
@ -28,27 +28,27 @@ function getPoints(data) {
return data.map(d => d.position); return data.map(d => d.position);
} }
function setTooltipContent(formData) { function setTooltipContent(formData, verboseMap) {
return o => ( return o => {
<div className="deckgl-tooltip"> const label =
<TooltipRow verboseMap?.[formData.point_radius_fixed.value] ||
label={`${t('Longitude and Latitude')}: `} getMetricLabel(formData.point_radius_fixed?.value);
value={`${o.object.position[0]}, ${o.object.position[1]}`} return (
/> <div className="deckgl-tooltip">
{o.object.cat_color && (
<TooltipRow label={`${t('Category')}: `} value={`${o.object.cat_color}`} />
)}
{o.object.metric && (
<TooltipRow <TooltipRow
label={`${formData.point_radius_fixed.value.label}: `} label={`${t('Longitude and Latitude')}: `}
value={`${o.object.metric}`} value={`${o.object.position[0]}, ${o.object.position[1]}`}
/> />
)} {o.object.cat_color && (
</div> <TooltipRow label={`${t('Category')}: `} value={`${o.object.cat_color}`} />
); )}
{o.object.metric && <TooltipRow label={`${label}: `} value={`${o.object.metric}`} />}
</div>
);
};
} }
export function getLayer(formData, payload, onAddFilter, setTooltip) { export function getLayer(formData, payload, onAddFilter, setTooltip, datasource) {
const fd = formData; const fd = formData;
const dataWithRadius = payload.data.features.map(d => { const dataWithRadius = payload.data.features.map(d => {
let radius = unitToRadius(fd.point_unit, d.radius) || 10; let radius = unitToRadius(fd.point_unit, d.radius) || 10;
@ -73,7 +73,7 @@ export function getLayer(formData, payload, onAddFilter, setTooltip) {
radiusMinPixels: fd.min_radius || null, radiusMinPixels: fd.min_radius || null,
radiusMaxPixels: fd.max_radius || null, radiusMaxPixels: fd.max_radius || null,
stroked: false, stroked: false,
...commonLayerProps(fd, setTooltip, setTooltipContent(fd)), ...commonLayerProps(fd, setTooltip, setTooltipContent(fd, datasource?.verboseMap)),
}); });
} }

View File

@ -66,8 +66,8 @@ export default {
{ {
label: t('Point Size'), label: t('Point Size'),
controlSetRows: [ controlSetRows: [
[pointRadiusFixed],
[ [
pointRadiusFixed,
{ {
name: 'point_unit', name: 'point_unit',
config: { config: {
@ -125,17 +125,17 @@ export default {
{ {
label: t('Point Color'), label: t('Point Color'),
controlSetRows: [ controlSetRows: [
['color_picker', legendPosition], ['color_picker'],
[null, legendFormat], [legendPosition],
[legendFormat],
[ [
{ {
...dimension, ...dimension,
label: t('Categorical Color'), label: t('Categorical Color'),
description: t('Pick a dimension from which categorical colors are defined'), description: t('Pick a dimension from which categorical colors are defined'),
}, },
'color_scheme',
'label_colors',
], ],
['color_scheme'],
], ],
}, },
{ {

View File

@ -19,10 +19,11 @@
const NOOP = () => {}; const NOOP = () => {};
export default function transformProps(chartProps) { export default function transformProps(chartProps) {
const { width, height, rawFormData, queriesData, hooks } = chartProps; const { datasource, height, hooks, queriesData, rawFormData, width } = chartProps;
const { onAddFilter = NOOP, setControlValue = NOOP } = hooks; const { onAddFilter = NOOP, setControlValue = NOOP } = hooks;
return { return {
datasource,
formData: rawFormData, formData: rawFormData,
height, height,
onAddFilter, onAddFilter,