mirror of https://github.com/apache/superset.git
fix(explore): DndColumnSelect sometimes not working with multi: false (#15731)
* fix(explore): DndColumnSelect not working with multi: false * fix values not synchronized when dataset changes
This commit is contained in:
parent
0721f54580
commit
66c28d653f
|
@ -16,7 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React, { useState } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { tn } from '@superset-ui/core';
|
import { tn } from '@superset-ui/core';
|
||||||
import { ColumnMeta } from '@superset-ui/chart-controls';
|
import { ColumnMeta } from '@superset-ui/chart-controls';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
|
@ -29,19 +29,41 @@ import { DndItemType } from 'src/explore/components/DndItemType';
|
||||||
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
|
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
|
||||||
|
|
||||||
export const DndColumnSelect = (props: LabelProps) => {
|
export const DndColumnSelect = (props: LabelProps) => {
|
||||||
const { value, options, multi = true } = props;
|
const { value, options, multi = true, onChange } = props;
|
||||||
const optionSelector = new OptionSelector(options, value);
|
const optionSelector = new OptionSelector(options, multi, value);
|
||||||
const [values, setValues] = useState<ColumnMeta[]>(optionSelector.values);
|
|
||||||
|
// synchronize values in case of dataset changes
|
||||||
|
useEffect(() => {
|
||||||
|
const optionSelectorValues = optionSelector.getValues();
|
||||||
|
if (typeof value !== typeof optionSelectorValues) {
|
||||||
|
onChange(optionSelectorValues);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
typeof value === 'string' &&
|
||||||
|
typeof optionSelectorValues === 'string' &&
|
||||||
|
value !== optionSelectorValues
|
||||||
|
) {
|
||||||
|
onChange(optionSelectorValues);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
Array.isArray(optionSelectorValues) &&
|
||||||
|
Array.isArray(value) &&
|
||||||
|
(optionSelectorValues.length !== value.length ||
|
||||||
|
optionSelectorValues.every((val, index) => val === value[index]))
|
||||||
|
) {
|
||||||
|
onChange(optionSelectorValues);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [JSON.stringify(value), JSON.stringify(optionSelector.getValues())]);
|
||||||
|
|
||||||
const onDrop = (item: DatasourcePanelDndItem) => {
|
const onDrop = (item: DatasourcePanelDndItem) => {
|
||||||
const column = item.value as ColumnMeta;
|
const column = item.value as ColumnMeta;
|
||||||
if (!optionSelector.isArray && !isEmpty(optionSelector.values)) {
|
if (!optionSelector.multi && !isEmpty(optionSelector.values)) {
|
||||||
optionSelector.replace(0, column.column_name);
|
optionSelector.replace(0, column.column_name);
|
||||||
} else {
|
} else {
|
||||||
optionSelector.add(column.column_name);
|
optionSelector.add(column.column_name);
|
||||||
}
|
}
|
||||||
setValues(optionSelector.values);
|
onChange(optionSelector.getValues());
|
||||||
props.onChange(optionSelector.getValues());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const canDrop = (item: DatasourcePanelDndItem) =>
|
const canDrop = (item: DatasourcePanelDndItem) =>
|
||||||
|
@ -50,18 +72,16 @@ export const DndColumnSelect = (props: LabelProps) => {
|
||||||
|
|
||||||
const onClickClose = (index: number) => {
|
const onClickClose = (index: number) => {
|
||||||
optionSelector.del(index);
|
optionSelector.del(index);
|
||||||
setValues(optionSelector.values);
|
onChange(optionSelector.getValues());
|
||||||
props.onChange(optionSelector.getValues());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onShiftOptions = (dragIndex: number, hoverIndex: number) => {
|
const onShiftOptions = (dragIndex: number, hoverIndex: number) => {
|
||||||
optionSelector.swap(dragIndex, hoverIndex);
|
optionSelector.swap(dragIndex, hoverIndex);
|
||||||
setValues(optionSelector.values);
|
onChange(optionSelector.getValues());
|
||||||
props.onChange(optionSelector.getValues());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const valuesRenderer = () =>
|
const valuesRenderer = () =>
|
||||||
values.map((column, idx) => (
|
optionSelector.values.map((column, idx) => (
|
||||||
<OptionWrapper
|
<OptionWrapper
|
||||||
key={idx}
|
key={idx}
|
||||||
index={idx}
|
index={idx}
|
||||||
|
|
|
@ -17,28 +17,23 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { ColumnMeta } from '@superset-ui/chart-controls';
|
import { ColumnMeta } from '@superset-ui/chart-controls';
|
||||||
|
import { ensureIsArray } from '@superset-ui/core';
|
||||||
|
|
||||||
export class OptionSelector {
|
export class OptionSelector {
|
||||||
values: ColumnMeta[];
|
values: ColumnMeta[];
|
||||||
|
|
||||||
options: { string: ColumnMeta };
|
options: { string: ColumnMeta };
|
||||||
|
|
||||||
isArray: boolean;
|
multi: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
options: { string: ColumnMeta },
|
options: { string: ColumnMeta },
|
||||||
|
multi: boolean,
|
||||||
initialValues?: string[] | string,
|
initialValues?: string[] | string,
|
||||||
) {
|
) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
let values: string[];
|
this.multi = multi;
|
||||||
if (Array.isArray(initialValues)) {
|
this.values = ensureIsArray(initialValues)
|
||||||
values = initialValues;
|
|
||||||
this.isArray = true;
|
|
||||||
} else {
|
|
||||||
values = initialValues ? [initialValues] : [];
|
|
||||||
this.isArray = false;
|
|
||||||
}
|
|
||||||
this.values = values
|
|
||||||
.map(value => {
|
.map(value => {
|
||||||
if (value in options) {
|
if (value in options) {
|
||||||
return options[value];
|
return options[value];
|
||||||
|
@ -68,12 +63,12 @@ export class OptionSelector {
|
||||||
[this.values[a], this.values[b]] = [this.values[b], this.values[a]];
|
[this.values[a], this.values[b]] = [this.values[b], this.values[a]];
|
||||||
}
|
}
|
||||||
|
|
||||||
has(groupBy: string): boolean {
|
has(value: string): boolean {
|
||||||
return !!this.getValues()?.includes(groupBy);
|
return !!this.getValues()?.includes(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
getValues(): string[] | string | undefined {
|
getValues(): string[] | string | undefined {
|
||||||
if (!this.isArray) {
|
if (!this.multi) {
|
||||||
return this.values.length > 0 ? this.values[0].column_name : undefined;
|
return this.values.length > 0 ? this.values[0].column_name : undefined;
|
||||||
}
|
}
|
||||||
return this.values.map(option => option.column_name);
|
return this.values.map(option => option.column_name);
|
||||||
|
|
Loading…
Reference in New Issue