mirror of
https://github.com/apache/superset.git
synced 2024-09-12 00:29:39 -04:00
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)
|
.filter(key => !selectedValues.hasOwnProperty(key)
|
||||||
|| !(key in filtersChoices))
|
|| !(key in filtersChoices))
|
||||||
.forEach((key) => {
|
.forEach((key) => {
|
||||||
const choices = filtersChoices[key];
|
const choices = filtersChoices[key] || [];
|
||||||
const choiceIds = new Set(choices.map(f => f.id));
|
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))
|
.filter(value => !choiceIds.has(value))
|
||||||
.forEach((value) => {
|
.forEach((value) => {
|
||||||
choices.unshift({
|
choices.unshift({
|
||||||
|
@ -14,34 +14,37 @@ const propTypes = {
|
|||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
viewport: PropTypes.object.isRequired,
|
viewport: PropTypes.object.isRequired,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
|
onViewportChange: PropTypes.func,
|
||||||
|
onValuesChange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
aggregation: false,
|
aggregation: false,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
onViewportChange: () => {},
|
||||||
|
onValuesChange: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class AnimatableDeckGLContainer extends React.Component {
|
export default class AnimatableDeckGLContainer extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
const { getLayers, start, end, getStep, values, disabled, viewport, ...other } = props;
|
const { getLayers, start, end, getStep, values, disabled, viewport, ...other } = props;
|
||||||
this.state = { values, viewport };
|
|
||||||
this.other = other;
|
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() {
|
render() {
|
||||||
const { start, end, getStep, disabled, aggregation, children, getLayers } = this.props;
|
const {
|
||||||
const { values, viewport } = this.state;
|
start,
|
||||||
|
end,
|
||||||
|
getStep,
|
||||||
|
disabled,
|
||||||
|
aggregation,
|
||||||
|
children,
|
||||||
|
getLayers,
|
||||||
|
values,
|
||||||
|
viewport,
|
||||||
|
onViewportChange,
|
||||||
|
onValuesChange,
|
||||||
|
} = this.props;
|
||||||
const layers = getLayers(values);
|
const layers = getLayers(values);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -49,7 +52,7 @@ export default class AnimatableDeckGLContainer extends React.Component {
|
|||||||
{...this.other}
|
{...this.other}
|
||||||
viewport={viewport}
|
viewport={viewport}
|
||||||
layers={layers}
|
layers={layers}
|
||||||
onViewportChange={newViewport => this.setState({ viewport: newViewport })}
|
onViewportChange={onViewportChange}
|
||||||
/>
|
/>
|
||||||
{!disabled &&
|
{!disabled &&
|
||||||
<PlaySlider
|
<PlaySlider
|
||||||
@ -58,7 +61,7 @@ export default class AnimatableDeckGLContainer extends React.Component {
|
|||||||
step={getStep(start)}
|
step={getStep(start)}
|
||||||
values={values}
|
values={values}
|
||||||
range={!aggregation}
|
range={!aggregation}
|
||||||
onChange={this.onChange}
|
onChange={onValuesChange}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{children}
|
{children}
|
||||||
|
@ -48,28 +48,31 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
|
|||||||
* The container will have an interactive legend, populated from the
|
* The container will have an interactive legend, populated from the
|
||||||
* categories present in the data.
|
* 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) {
|
constructor(props) {
|
||||||
super(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.getLayers = this.getLayers.bind(this);
|
||||||
|
this.onValuesChange = this.onValuesChange.bind(this);
|
||||||
|
this.onViewportChange = this.onViewportChange.bind(this);
|
||||||
this.toggleCategory = this.toggleCategory.bind(this);
|
this.toggleCategory = this.toggleCategory.bind(this);
|
||||||
this.showSingleCategory = this.showSingleCategory.bind(this);
|
this.showSingleCategory = this.showSingleCategory.bind(this);
|
||||||
}
|
}
|
||||||
componentWillReceiveProps(nextProps) {
|
onValuesChange(values) {
|
||||||
this.setState(CategoricalDeckGLContainer.getDerivedStateFromProps(nextProps, this.state));
|
this.setState({
|
||||||
|
values: Array.isArray(values)
|
||||||
|
? values
|
||||||
|
: [values, values + this.state.getStep(values)],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onViewportChange(viewport) {
|
||||||
|
this.setState({ viewport });
|
||||||
}
|
}
|
||||||
getLayers(values) {
|
getLayers(values) {
|
||||||
const {
|
const {
|
||||||
@ -79,31 +82,35 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
|
|||||||
onAddFilter,
|
onAddFilter,
|
||||||
setTooltip,
|
setTooltip,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
let data = [...payload.data.features];
|
let features = [...payload.data.features];
|
||||||
|
|
||||||
// Add colors from categories or fixed color
|
// Add colors from categories or fixed color
|
||||||
data = this.addColor(data, fd);
|
features = this.addColor(features, fd);
|
||||||
|
|
||||||
// Apply user defined data mutator if defined
|
// Apply user defined data mutator if defined
|
||||||
if (fd.js_data_mutator) {
|
if (fd.js_data_mutator) {
|
||||||
const jsFnMutator = sandboxedEval(fd.js_data_mutator);
|
const jsFnMutator = sandboxedEval(fd.js_data_mutator);
|
||||||
data = jsFnMutator(data);
|
features = jsFnMutator(features);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by time
|
// Filter by time
|
||||||
if (values[0] === values[1] || values[1] === this.end) {
|
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 {
|
} 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
|
// Show only categories selected in the legend
|
||||||
if (fd.dimension) {
|
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;
|
const filteredPayload = {
|
||||||
return [getLayer(fd, payload, onAddFilter, setTooltip)];
|
...payload,
|
||||||
|
data: { ...payload.data, features },
|
||||||
|
};
|
||||||
|
|
||||||
|
return [getLayer(fd, filteredPayload, onAddFilter, setTooltip)];
|
||||||
}
|
}
|
||||||
addColor(data, fd) {
|
addColor(data, fd) {
|
||||||
const c = fd.color_picker || { r: 0, g: 0, b: 0, a: 1 };
|
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}
|
end={this.state.end}
|
||||||
getStep={this.state.getStep}
|
getStep={this.state.getStep}
|
||||||
values={this.state.values}
|
values={this.state.values}
|
||||||
|
onValuesChange={this.onValuesChange}
|
||||||
disabled={this.state.disabled}
|
disabled={this.state.disabled}
|
||||||
viewport={this.props.viewport}
|
viewport={this.state.viewport}
|
||||||
|
onViewportChange={this.onViewportChange}
|
||||||
mapboxApiAccessToken={this.props.mapboxApiKey}
|
mapboxApiAccessToken={this.props.mapboxApiKey}
|
||||||
mapStyle={this.props.formData.mapbox_style}
|
mapStyle={this.props.formData.mapbox_style}
|
||||||
setControlValue={this.props.setControlValue}
|
setControlValue={this.props.setControlValue}
|
||||||
|
@ -62,24 +62,31 @@ const defaultProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class DeckGLScreenGrid extends React.PureComponent {
|
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) {
|
constructor(props) {
|
||||||
super(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.getLayers = this.getLayers.bind(this);
|
||||||
|
this.onValuesChange = this.onValuesChange.bind(this);
|
||||||
|
this.onViewportChange = this.onViewportChange.bind(this);
|
||||||
}
|
}
|
||||||
componentWillReceiveProps(nextProps) {
|
onValuesChange(values) {
|
||||||
this.setState(DeckGLScreenGrid.getDerivedStateFromProps(nextProps, this.state));
|
this.setState({
|
||||||
|
values: Array.isArray(values)
|
||||||
|
? values
|
||||||
|
: [values, values + this.state.getStep(values)],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onViewportChange(viewport) {
|
||||||
|
this.setState({ viewport });
|
||||||
}
|
}
|
||||||
getLayers(values) {
|
getLayers(values) {
|
||||||
const filters = [];
|
const filters = [];
|
||||||
@ -102,11 +109,7 @@ class DeckGLScreenGrid extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { formData, payload } = this.props;
|
const { formData, payload, setControlValue } = this.props;
|
||||||
const viewport = formData.autozoom
|
|
||||||
? fitViewport(this.props.viewport, getPoints(payload.data.features))
|
|
||||||
: this.props.viewport;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AnimatableDeckGLContainer
|
<AnimatableDeckGLContainer
|
||||||
@ -115,11 +118,13 @@ class DeckGLScreenGrid extends React.PureComponent {
|
|||||||
end={this.state.end}
|
end={this.state.end}
|
||||||
getStep={this.state.getStep}
|
getStep={this.state.getStep}
|
||||||
values={this.state.values}
|
values={this.state.values}
|
||||||
|
onValuesChange={this.onValuesChange}
|
||||||
disabled={this.state.disabled}
|
disabled={this.state.disabled}
|
||||||
viewport={viewport}
|
viewport={this.state.viewport}
|
||||||
mapboxApiAccessToken={this.props.payload.data.mapboxApiKey}
|
onViewportChange={this.onViewportChange}
|
||||||
mapStyle={this.props.formData.mapbox_style}
|
mapboxApiAccessToken={payload.data.mapboxApiKey}
|
||||||
setControlValue={this.props.setControlValue}
|
mapStyle={formData.mapbox_style}
|
||||||
|
setControlValue={setControlValue}
|
||||||
aggregation
|
aggregation
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user