mirror of https://github.com/apache/superset.git
Fixes to the CategoricalDeckGLContainer and filter box (#6038)
* WIP * WIP * Fix time grain * Fix autoformatting * Fix more autoformatting * Fix even more autoformatting * Fix manual move of play slider * Fix state management * Revert change * Fix screengrid * Remove autozoom on render * Remove unneeded code * Zoom when mounted * Fix lint
This commit is contained in:
parent
91792a564a
commit
b4a1983303
|
@ -181,9 +181,12 @@ class FilterBox extends React.Component {
|
|||
.filter(key => !selectedValues.hasOwnProperty(key)
|
||||
|| !(key in filtersChoices))
|
||||
.forEach((key) => {
|
||||
const choices = filtersChoices[key];
|
||||
const choices = filtersChoices[key] || [];
|
||||
const choiceIds = new Set(choices.map(f => f.id));
|
||||
selectedValues[key]
|
||||
const selectedValuesForKey = Array.isArray(selectedValues[key])
|
||||
? selectedValues[key]
|
||||
: [selectedValues[key]];
|
||||
selectedValuesForKey
|
||||
.filter(value => !choiceIds.has(value))
|
||||
.forEach((value) => {
|
||||
choices.unshift({
|
||||
|
|
|
@ -14,34 +14,37 @@ const propTypes = {
|
|||
disabled: PropTypes.bool,
|
||||
viewport: PropTypes.object.isRequired,
|
||||
children: PropTypes.node,
|
||||
onViewportChange: PropTypes.func,
|
||||
onValuesChange: PropTypes.func,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
aggregation: false,
|
||||
disabled: false,
|
||||
onViewportChange: () => {},
|
||||
onValuesChange: () => {},
|
||||
};
|
||||
|
||||
export default class AnimatableDeckGLContainer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { getLayers, start, end, getStep, values, disabled, viewport, ...other } = props;
|
||||
this.state = { values, viewport };
|
||||
this.other = other;
|
||||
this.onChange = this.onChange.bind(this);
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState({ values: nextProps.values, viewport: nextProps.viewport });
|
||||
}
|
||||
onChange(newValues) {
|
||||
this.setState({
|
||||
values: Array.isArray(newValues)
|
||||
? newValues
|
||||
: [newValues, this.props.getStep(newValues)],
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const { start, end, getStep, disabled, aggregation, children, getLayers } = this.props;
|
||||
const { values, viewport } = this.state;
|
||||
const {
|
||||
start,
|
||||
end,
|
||||
getStep,
|
||||
disabled,
|
||||
aggregation,
|
||||
children,
|
||||
getLayers,
|
||||
values,
|
||||
viewport,
|
||||
onViewportChange,
|
||||
onValuesChange,
|
||||
} = this.props;
|
||||
const layers = getLayers(values);
|
||||
return (
|
||||
<div>
|
||||
|
@ -49,7 +52,7 @@ export default class AnimatableDeckGLContainer extends React.Component {
|
|||
{...this.other}
|
||||
viewport={viewport}
|
||||
layers={layers}
|
||||
onViewportChange={newViewport => this.setState({ viewport: newViewport })}
|
||||
onViewportChange={onViewportChange}
|
||||
/>
|
||||
{!disabled &&
|
||||
<PlaySlider
|
||||
|
@ -58,7 +61,7 @@ export default class AnimatableDeckGLContainer extends React.Component {
|
|||
step={getStep(start)}
|
||||
values={values}
|
||||
range={!aggregation}
|
||||
onChange={this.onChange}
|
||||
onChange={onValuesChange}
|
||||
/>
|
||||
}
|
||||
{children}
|
||||
|
|
|
@ -48,28 +48,31 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
|
|||
* The container will have an interactive legend, populated from the
|
||||
* categories present in the data.
|
||||
*/
|
||||
|
||||
/* eslint-disable-next-line react/sort-comp */
|
||||
static getDerivedStateFromProps(nextProps) {
|
||||
const fd = nextProps.formData;
|
||||
|
||||
const timeGrain = fd.time_grain_sqla || fd.granularity || 'PT1M';
|
||||
const timestamps = nextProps.payload.data.features.map(f => f.__timestamp);
|
||||
const { start, end, getStep, values, disabled } = getPlaySliderParams(timestamps, timeGrain);
|
||||
const categories = getCategories(fd, nextProps.payload.data.features);
|
||||
|
||||
return { start, end, getStep, values, disabled, categories };
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = CategoricalDeckGLContainer.getDerivedStateFromProps(props);
|
||||
|
||||
const fd = props.formData;
|
||||
const timeGrain = fd.time_grain_sqla || fd.granularity || 'PT1M';
|
||||
const timestamps = props.payload.data.features.map(f => f.__timestamp);
|
||||
const { start, end, getStep, values, disabled } = getPlaySliderParams(timestamps, timeGrain);
|
||||
const categories = getCategories(fd, props.payload.data.features);
|
||||
this.state = { start, end, getStep, values, disabled, categories, viewport: props.viewport };
|
||||
|
||||
this.getLayers = this.getLayers.bind(this);
|
||||
this.onValuesChange = this.onValuesChange.bind(this);
|
||||
this.onViewportChange = this.onViewportChange.bind(this);
|
||||
this.toggleCategory = this.toggleCategory.bind(this);
|
||||
this.showSingleCategory = this.showSingleCategory.bind(this);
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState(CategoricalDeckGLContainer.getDerivedStateFromProps(nextProps, this.state));
|
||||
onValuesChange(values) {
|
||||
this.setState({
|
||||
values: Array.isArray(values)
|
||||
? values
|
||||
: [values, values + this.state.getStep(values)],
|
||||
});
|
||||
}
|
||||
onViewportChange(viewport) {
|
||||
this.setState({ viewport });
|
||||
}
|
||||
getLayers(values) {
|
||||
const {
|
||||
|
@ -79,31 +82,35 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
|
|||
onAddFilter,
|
||||
setTooltip,
|
||||
} = this.props;
|
||||
let data = [...payload.data.features];
|
||||
let features = [...payload.data.features];
|
||||
|
||||
// Add colors from categories or fixed color
|
||||
data = this.addColor(data, fd);
|
||||
features = this.addColor(features, fd);
|
||||
|
||||
// Apply user defined data mutator if defined
|
||||
if (fd.js_data_mutator) {
|
||||
const jsFnMutator = sandboxedEval(fd.js_data_mutator);
|
||||
data = jsFnMutator(data);
|
||||
features = jsFnMutator(features);
|
||||
}
|
||||
|
||||
// Filter by time
|
||||
if (values[0] === values[1] || values[1] === this.end) {
|
||||
data = data.filter(d => d.__timestamp >= values[0] && d.__timestamp <= values[1]);
|
||||
features = features.filter(d => d.__timestamp >= values[0] && d.__timestamp <= values[1]);
|
||||
} else {
|
||||
data = data.filter(d => d.__timestamp >= values[0] && d.__timestamp < values[1]);
|
||||
features = features.filter(d => d.__timestamp >= values[0] && d.__timestamp < values[1]);
|
||||
}
|
||||
|
||||
// Show only categories selected in the legend
|
||||
if (fd.dimension) {
|
||||
data = data.filter(d => this.state.categories[d.cat_color].enabled);
|
||||
features = features.filter(d => this.state.categories[d.cat_color].enabled);
|
||||
}
|
||||
|
||||
payload.data.features = data;
|
||||
return [getLayer(fd, payload, onAddFilter, setTooltip)];
|
||||
const filteredPayload = {
|
||||
...payload,
|
||||
data: { ...payload.data, features },
|
||||
};
|
||||
|
||||
return [getLayer(fd, filteredPayload, onAddFilter, setTooltip)];
|
||||
}
|
||||
addColor(data, fd) {
|
||||
const c = fd.color_picker || { r: 0, g: 0, b: 0, a: 1 };
|
||||
|
@ -146,8 +153,10 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
|
|||
end={this.state.end}
|
||||
getStep={this.state.getStep}
|
||||
values={this.state.values}
|
||||
onValuesChange={this.onValuesChange}
|
||||
disabled={this.state.disabled}
|
||||
viewport={this.props.viewport}
|
||||
viewport={this.state.viewport}
|
||||
onViewportChange={this.onViewportChange}
|
||||
mapboxApiAccessToken={this.props.mapboxApiKey}
|
||||
mapStyle={this.props.formData.mapbox_style}
|
||||
setControlValue={this.props.setControlValue}
|
||||
|
|
|
@ -62,24 +62,31 @@ const defaultProps = {
|
|||
};
|
||||
|
||||
class DeckGLScreenGrid extends React.PureComponent {
|
||||
/* eslint-disable-next-line react/sort-comp */
|
||||
static getDerivedStateFromProps(nextProps) {
|
||||
const fd = nextProps.formData;
|
||||
|
||||
const timeGrain = fd.time_grain_sqla || fd.granularity || 'PT1M';
|
||||
const timestamps = nextProps.payload.data.features.map(f => f.__timestamp);
|
||||
const { start, end, getStep, values, disabled } = getPlaySliderParams(timestamps, timeGrain);
|
||||
|
||||
return { start, end, getStep, values, disabled };
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = DeckGLScreenGrid.getDerivedStateFromProps(props);
|
||||
|
||||
const fd = props.formData;
|
||||
const timeGrain = fd.time_grain_sqla || fd.granularity || 'PT1M';
|
||||
const timestamps = props.payload.data.features.map(f => f.__timestamp);
|
||||
const { start, end, getStep, values, disabled } = getPlaySliderParams(timestamps, timeGrain);
|
||||
const viewport = fd.autozoom
|
||||
? fitViewport(props.viewport, getPoints(props.payload.data.features))
|
||||
: props.viewport;
|
||||
this.state = { start, end, getStep, values, disabled, viewport };
|
||||
|
||||
this.getLayers = this.getLayers.bind(this);
|
||||
this.onValuesChange = this.onValuesChange.bind(this);
|
||||
this.onViewportChange = this.onViewportChange.bind(this);
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState(DeckGLScreenGrid.getDerivedStateFromProps(nextProps, this.state));
|
||||
onValuesChange(values) {
|
||||
this.setState({
|
||||
values: Array.isArray(values)
|
||||
? values
|
||||
: [values, values + this.state.getStep(values)],
|
||||
});
|
||||
}
|
||||
onViewportChange(viewport) {
|
||||
this.setState({ viewport });
|
||||
}
|
||||
getLayers(values) {
|
||||
const filters = [];
|
||||
|
@ -102,11 +109,7 @@ class DeckGLScreenGrid extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { formData, payload } = this.props;
|
||||
const viewport = formData.autozoom
|
||||
? fitViewport(this.props.viewport, getPoints(payload.data.features))
|
||||
: this.props.viewport;
|
||||
|
||||
const { formData, payload, setControlValue } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<AnimatableDeckGLContainer
|
||||
|
@ -115,11 +118,13 @@ class DeckGLScreenGrid extends React.PureComponent {
|
|||
end={this.state.end}
|
||||
getStep={this.state.getStep}
|
||||
values={this.state.values}
|
||||
onValuesChange={this.onValuesChange}
|
||||
disabled={this.state.disabled}
|
||||
viewport={viewport}
|
||||
mapboxApiAccessToken={this.props.payload.data.mapboxApiKey}
|
||||
mapStyle={this.props.formData.mapbox_style}
|
||||
setControlValue={this.props.setControlValue}
|
||||
viewport={this.state.viewport}
|
||||
onViewportChange={this.onViewportChange}
|
||||
mapboxApiAccessToken={payload.data.mapboxApiKey}
|
||||
mapStyle={formData.mapbox_style}
|
||||
setControlValue={setControlValue}
|
||||
aggregation
|
||||
/>
|
||||
</div>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue