feat: move filters from superset-ui to incubator (#12154)
* feat: move filters from superset-ui to incubator * refactor: add safety check * refactor: move extraForm data utils * refactor: move extraForm data utils * lint: fix lint * chore: add license * chore: undo changes to file * refactor: fix CR notes / add tests * test: update tests * fix: fix range logic Co-authored-by: Amit Miran <47772523+amitmiran137@users.noreply.github.com>
This commit is contained in:
parent
d760e885d7
commit
fecfc34cd3
|
|
@ -0,0 +1,156 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
getRangeExtraFormData,
|
||||
getSelectExtraFormData,
|
||||
} from '../../../src/filters/utils';
|
||||
|
||||
describe('Filter utils', () => {
|
||||
describe('getRangeExtraFormData', () => {
|
||||
it('getRangeExtraFormData - col: "testCol", lower: 1, upper: 2', () => {
|
||||
expect(getRangeExtraFormData('testCol', 1, 2)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 1,
|
||||
},
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
it('getRangeExtraFormData - col: "testCol", lower: 0, upper: 0', () => {
|
||||
expect(getRangeExtraFormData('testCol', 0, 0)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 0,
|
||||
},
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
it('getRangeExtraFormData - col: "testCol", lower: null, upper: 2', () => {
|
||||
expect(getRangeExtraFormData('testCol', null, 2)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
it('getRangeExtraFormData - col: "testCol", lower: 1, upper: undefined', () => {
|
||||
expect(getRangeExtraFormData('testCol', 1, undefined)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('getSelectExtraFormData', () => {
|
||||
it('getSelectExtraFormData - col: "testCol", value: ["value"], emptyFilter: false, inverseSelection: false', () => {
|
||||
expect(
|
||||
getSelectExtraFormData('testCol', ['value'], false, false),
|
||||
).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: 'IN',
|
||||
val: ['value'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: ["value"], emptyFilter: true, inverseSelection: false', () => {
|
||||
expect(getSelectExtraFormData('testCol', ['value'], true, false)).toEqual(
|
||||
{
|
||||
append_form_data: {
|
||||
extras: {
|
||||
where: '1 = 0',
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: ["value"], emptyFilter: false, inverseSelection: true', () => {
|
||||
expect(getSelectExtraFormData('testCol', ['value'], false, true)).toEqual(
|
||||
{
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: 'NOT IN',
|
||||
val: ['value'],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: [], emptyFilter: false, inverseSelection: false', () => {
|
||||
expect(getSelectExtraFormData('testCol', [], false, false)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: undefined, emptyFilter: false, inverseSelection: false', () => {
|
||||
expect(
|
||||
getSelectExtraFormData('testCol', undefined, false, false),
|
||||
).toEqual({
|
||||
append_form_data: {
|
||||
filters: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: null, emptyFilter: false, inverseSelection: false', () => {
|
||||
expect(getSelectExtraFormData('testCol', null, false, false)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -44,6 +44,7 @@ export {
|
|||
Typography,
|
||||
Tree,
|
||||
Popover,
|
||||
Slider,
|
||||
Radio,
|
||||
Row,
|
||||
Select,
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ const FilterValue: React.FC<FilterProps> = ({
|
|||
} = filter;
|
||||
const cascadingFilters = useCascadingFilters(id);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [state, setState] = useState({ data: undefined });
|
||||
const [state, setState] = useState([]);
|
||||
const [formData, setFormData] = useState<Partial<QueryFormData>>({});
|
||||
const [target] = targets;
|
||||
const { datasetId = 18, column } = target;
|
||||
|
|
@ -256,7 +256,7 @@ const FilterValue: React.FC<FilterProps> = ({
|
|||
force: false,
|
||||
requestParams: { dashboardId: 0 },
|
||||
}).then(response => {
|
||||
setState({ data: response.result[0].data });
|
||||
setState(response.result);
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { styled } from '@superset-ui/core';
|
||||
import React from 'react';
|
||||
import { Slider } from 'src/common/components';
|
||||
import { AntdPluginFilterRangeProps } from './types';
|
||||
import { AntdPluginFilterStylesProps } from '../types';
|
||||
import { getRangeExtraFormData } from '../../utils';
|
||||
|
||||
const Styles = styled.div<AntdPluginFilterStylesProps>`
|
||||
height: ${({ height }) => height};
|
||||
width: ${({ width }) => width};
|
||||
`;
|
||||
|
||||
export default function AntdRangeFilter(props: AntdPluginFilterRangeProps) {
|
||||
const { data, formData, height, width, setExtraFormData } = props;
|
||||
const [row] = data;
|
||||
// @ts-ignore
|
||||
const { min, max }: { min: number; max: number } = row;
|
||||
const { groupby } = formData;
|
||||
const [col] = groupby || [];
|
||||
|
||||
const handleChange = (value: [number, number]) => {
|
||||
const [lower, upper] = value;
|
||||
|
||||
setExtraFormData(getRangeExtraFormData(col, lower, upper));
|
||||
};
|
||||
|
||||
return (
|
||||
<Styles height={height} width={width}>
|
||||
<Slider
|
||||
range
|
||||
min={min}
|
||||
max={max}
|
||||
defaultValue={[min, max]}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</Styles>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
buildQueryContext,
|
||||
ColumnType,
|
||||
QueryFormData,
|
||||
} from '@superset-ui/core';
|
||||
|
||||
/**
|
||||
* The buildQuery function is used to create an instance of QueryContext that's
|
||||
* sent to the chart data endpoint. In addition to containing information of which
|
||||
* datasource to use, it specifies the type (e.g. full payload, samples, query) and
|
||||
* format (e.g. CSV or JSON) of the result and whether or not to force refresh the data from
|
||||
* the datasource as opposed to using a cached copy of the data, if available.
|
||||
*
|
||||
* More importantly though, QueryContext contains a property `queries`, which is an array of
|
||||
* QueryObjects specifying individual data requests to be made. A QueryObject specifies which
|
||||
* columns, metrics and filters, among others, to use during the query. Usually it will be enough
|
||||
* to specify just one query based on the baseQueryObject, but for some more advanced use cases
|
||||
* it is possible to define post processing operations in the QueryObject, or multiple queries
|
||||
* if a viz needs multiple different result sets.
|
||||
*/
|
||||
export default function buildQuery(formData: QueryFormData) {
|
||||
const { groupby } = formData;
|
||||
const [column] = groupby || [];
|
||||
return buildQueryContext(formData, baseQueryObject => {
|
||||
return [
|
||||
{
|
||||
...baseQueryObject,
|
||||
groupby: [],
|
||||
metrics: [
|
||||
{
|
||||
aggregate: 'MIN',
|
||||
column: {
|
||||
columnName: column,
|
||||
id: 1,
|
||||
type: ColumnType.FLOAT,
|
||||
},
|
||||
expressionType: 'SIMPLE',
|
||||
hasCustomLabel: true,
|
||||
label: 'min',
|
||||
},
|
||||
{
|
||||
aggregate: 'MAX',
|
||||
column: {
|
||||
columnName: column,
|
||||
id: 2,
|
||||
type: ColumnType.FLOAT,
|
||||
},
|
||||
expressionType: 'SIMPLE',
|
||||
hasCustomLabel: true,
|
||||
label: 'max',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { t, validateNonEmpty } from '@superset-ui/core';
|
||||
import { ControlPanelConfig, sections } from '@superset-ui/chart-controls';
|
||||
|
||||
const config: ControlPanelConfig = {
|
||||
// For control input types, see: superset-frontend/src/explore/components/controls/index.js
|
||||
controlPanelSections: [
|
||||
// @ts-ignore
|
||||
sections.legacyRegularTime,
|
||||
{
|
||||
label: t('Query'),
|
||||
expanded: true,
|
||||
controlSetRows: [['groupby'], ['adhoc_filters']],
|
||||
},
|
||||
],
|
||||
controlOverrides: {
|
||||
groupby: {
|
||||
validators: [validateNonEmpty],
|
||||
clearable: false,
|
||||
},
|
||||
row_limit: {
|
||||
default: 100,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
|
||||
import buildQuery from './buildQuery';
|
||||
import controlPanel from './controlPanel';
|
||||
import transformProps from './transformProps';
|
||||
import thumbnail from './images/thumbnail.png';
|
||||
|
||||
export default class AntdRangeFilterPlugin extends ChartPlugin {
|
||||
constructor() {
|
||||
const metadata = new ChartMetadata({
|
||||
name: t('Range Filter Plugin'),
|
||||
description: 'Range Filter Plugin using AntD',
|
||||
isNativeFilter: true,
|
||||
thumbnail,
|
||||
});
|
||||
|
||||
super({
|
||||
buildQuery,
|
||||
controlPanel,
|
||||
loadChart: () => import('./AntdRangeFilter'),
|
||||
metadata,
|
||||
transformProps,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { ChartProps } from '@superset-ui/core';
|
||||
|
||||
export default function transformProps(chartProps: ChartProps) {
|
||||
const { formData, height, hooks, queriesData, width } = chartProps;
|
||||
const { setExtraFormData } = hooks;
|
||||
const { data } = queriesData[0];
|
||||
|
||||
return {
|
||||
data,
|
||||
formData,
|
||||
height,
|
||||
setExtraFormData,
|
||||
width,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
DataRecord,
|
||||
QueryFormData,
|
||||
SetExtraFormDataHook,
|
||||
} from '@superset-ui/core';
|
||||
import { AntdPluginFilterStylesProps } from '../types';
|
||||
|
||||
interface AntdPluginFilterSelectCustomizeProps {
|
||||
max?: number;
|
||||
min?: number;
|
||||
}
|
||||
|
||||
export type PluginFilterRangeQueryFormData = QueryFormData &
|
||||
AntdPluginFilterStylesProps &
|
||||
AntdPluginFilterSelectCustomizeProps;
|
||||
|
||||
export type AntdPluginFilterRangeProps = AntdPluginFilterStylesProps & {
|
||||
data: DataRecord[];
|
||||
formData: PluginFilterRangeQueryFormData;
|
||||
setExtraFormData: SetExtraFormDataHook;
|
||||
};
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { styled } from '@superset-ui/core';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Select } from 'src/common/components';
|
||||
import { DEFAULT_FORM_DATA, AntdPluginFilterSelectProps } from './types';
|
||||
import { AntdPluginFilterStylesProps } from '../types';
|
||||
import { getSelectExtraFormData } from '../../utils';
|
||||
|
||||
const Styles = styled.div<AntdPluginFilterStylesProps>`
|
||||
height: ${({ height }) => height};
|
||||
width: ${({ width }) => width};
|
||||
`;
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
export default function AntdPluginFilterSelect(
|
||||
props: AntdPluginFilterSelectProps,
|
||||
) {
|
||||
const [values, setValues] = useState<(string | number)[]>([]);
|
||||
const { data, formData, height, width, setExtraFormData } = props;
|
||||
const {
|
||||
defaultValues,
|
||||
enableEmptyFilter,
|
||||
multiSelect,
|
||||
showSearch,
|
||||
inverseSelection,
|
||||
} = {
|
||||
...DEFAULT_FORM_DATA,
|
||||
...formData,
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setValues(defaultValues || []);
|
||||
}, [defaultValues]);
|
||||
|
||||
let { groupby = [] } = formData;
|
||||
groupby = Array.isArray(groupby) ? groupby : [groupby];
|
||||
|
||||
function handleChange(value?: number[] | string[] | null) {
|
||||
setValues(value || []);
|
||||
const [col] = groupby;
|
||||
const emptyFilter =
|
||||
enableEmptyFilter &&
|
||||
!inverseSelection &&
|
||||
(value === undefined || value === null || value.length === 0);
|
||||
setExtraFormData(
|
||||
getSelectExtraFormData(col, value, emptyFilter, inverseSelection),
|
||||
);
|
||||
}
|
||||
const placeholderText =
|
||||
(data || []).length === 0
|
||||
? 'No data'
|
||||
: `${data.length} option${data.length > 1 ? 's' : 0}`;
|
||||
return (
|
||||
<Styles height={height} width={width}>
|
||||
<Select
|
||||
allowClear
|
||||
value={values}
|
||||
showSearch={showSearch}
|
||||
style={{ width: '100%' }}
|
||||
mode={multiSelect ? 'multiple' : undefined}
|
||||
placeholder={placeholderText}
|
||||
// @ts-ignore
|
||||
onChange={handleChange}
|
||||
>
|
||||
{(data || []).map(row => {
|
||||
const option = `${groupby.map(col => row[col])[0]}`;
|
||||
return (
|
||||
<Option key={option} value={option}>
|
||||
{option}
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Styles>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { buildQueryContext, QueryFormData } from '@superset-ui/core';
|
||||
|
||||
/**
|
||||
* The buildQuery function is used to create an instance of QueryContext that's
|
||||
* sent to the chart data endpoint. In addition to containing information of which
|
||||
* datasource to use, it specifies the type (e.g. full payload, samples, query) and
|
||||
* format (e.g. CSV or JSON) of the result and whether or not to force refresh the data from
|
||||
* the datasource as opposed to using a cached copy of the data, if available.
|
||||
*
|
||||
* More importantly though, QueryContext contains a property `queries`, which is an array of
|
||||
* QueryObjects specifying individual data requests to be made. A QueryObject specifies which
|
||||
* columns, metrics and filters, among others, to use during the query. Usually it will be enough
|
||||
* to specify just one query based on the baseQueryObject, but for some more advanced use cases
|
||||
* it is possible to define post processing operations in the QueryObject, or multiple queries
|
||||
* if a viz needs multiple different result sets.
|
||||
*/
|
||||
export default function buildQuery(formData: QueryFormData) {
|
||||
return buildQueryContext(formData, baseQueryObject => {
|
||||
return [
|
||||
{
|
||||
...baseQueryObject,
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { t, validateNonEmpty } from '@superset-ui/core';
|
||||
import { ControlPanelConfig, sections } from '@superset-ui/chart-controls';
|
||||
import { DEFAULT_FORM_DATA } from './types';
|
||||
|
||||
const {
|
||||
enableEmptyFilter,
|
||||
fetchPredicate,
|
||||
inverseSelection,
|
||||
multiSelect,
|
||||
showSearch,
|
||||
} = DEFAULT_FORM_DATA;
|
||||
|
||||
const config: ControlPanelConfig = {
|
||||
controlPanelSections: [
|
||||
// @ts-ignore
|
||||
sections.legacyRegularTime,
|
||||
{
|
||||
label: t('Query'),
|
||||
expanded: true,
|
||||
controlSetRows: [
|
||||
['groupby'],
|
||||
['metrics'],
|
||||
['adhoc_filters'],
|
||||
[
|
||||
{
|
||||
name: 'multiSelect',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Multiple Select'),
|
||||
default: multiSelect,
|
||||
description: t('Allow selecting multiple values'),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'enableEmptyFilter',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Enable Empty Filter'),
|
||||
default: enableEmptyFilter,
|
||||
description: t(
|
||||
'When selection is empty, should an always false filter event be emitted',
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'inverseSelection',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Inverse Selection'),
|
||||
default: inverseSelection,
|
||||
description: t('Exclude selected values'),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'showSearch',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Search Field'),
|
||||
default: showSearch,
|
||||
description: t('Allow typing search terms'),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'fetchPredicate',
|
||||
config: {
|
||||
type: 'TextControl',
|
||||
label: t('Fetch predicate'),
|
||||
default: fetchPredicate,
|
||||
description: t(
|
||||
'Predicate applied when fetching distinct value to populate the filter control component.',
|
||||
),
|
||||
},
|
||||
},
|
||||
null,
|
||||
],
|
||||
['row_limit', null],
|
||||
],
|
||||
},
|
||||
],
|
||||
controlOverrides: {
|
||||
groupby: {
|
||||
multi: false,
|
||||
validators: [validateNonEmpty],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
|
||||
import buildQuery from './buildQuery';
|
||||
import controlPanel from './controlPanel';
|
||||
import transformProps from './transformProps';
|
||||
import thumbnail from './images/thumbnail.png';
|
||||
|
||||
export default class AntdFilterSelectPlugin extends ChartPlugin {
|
||||
constructor() {
|
||||
const metadata = new ChartMetadata({
|
||||
name: t('Select Filter Plugin'),
|
||||
description: 'Select Filter Plugin using AntD',
|
||||
isNativeFilter: true,
|
||||
thumbnail,
|
||||
});
|
||||
|
||||
super({
|
||||
buildQuery,
|
||||
controlPanel,
|
||||
loadChart: () => import('./AntdSelectFilter'),
|
||||
metadata,
|
||||
transformProps,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { ChartProps } from '@superset-ui/core';
|
||||
import { DEFAULT_FORM_DATA } from './types';
|
||||
|
||||
export default function transformProps(chartProps: ChartProps) {
|
||||
const { formData, height, hooks, queriesData, width } = chartProps;
|
||||
const newFormData = { ...DEFAULT_FORM_DATA, ...formData };
|
||||
const { setExtraFormData = () => {} } = hooks;
|
||||
|
||||
const { data } = queriesData[0];
|
||||
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
data,
|
||||
formData: newFormData,
|
||||
setExtraFormData,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
QueryFormData,
|
||||
DataRecord,
|
||||
SetExtraFormDataHook,
|
||||
} from '@superset-ui/core';
|
||||
import { AntdPluginFilterStylesProps } from '../types';
|
||||
|
||||
interface AntdPluginFilterSelectCustomizeProps {
|
||||
defaultValues?: (string | number)[];
|
||||
enableEmptyFilter: boolean;
|
||||
fetchPredicate?: string;
|
||||
inverseSelection: boolean;
|
||||
multiSelect: boolean;
|
||||
showSearch: boolean;
|
||||
}
|
||||
|
||||
export type AntdPluginFilterSelectQueryFormData = QueryFormData &
|
||||
AntdPluginFilterStylesProps &
|
||||
AntdPluginFilterSelectCustomizeProps;
|
||||
|
||||
export type AntdPluginFilterSelectProps = AntdPluginFilterStylesProps & {
|
||||
data: DataRecord[];
|
||||
setExtraFormData: SetExtraFormDataHook;
|
||||
formData: AntdPluginFilterSelectQueryFormData;
|
||||
};
|
||||
|
||||
export const DEFAULT_FORM_DATA: AntdPluginFilterSelectCustomizeProps = {
|
||||
defaultValues: [],
|
||||
enableEmptyFilter: false,
|
||||
fetchPredicate: '',
|
||||
inverseSelection: false,
|
||||
multiSelect: true,
|
||||
showSearch: true,
|
||||
};
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
export { default as AntdSelectFilterPlugin } from './Select';
|
||||
export { default as AntdRangeFilterPlugin } from './Range';
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
export interface AntdPluginFilterStylesProps {
|
||||
height: number;
|
||||
width: number;
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { QueryObjectFilterClause } from '@superset-ui/core';
|
||||
|
||||
export const getSelectExtraFormData = (
|
||||
col: string,
|
||||
value?: undefined | null | string[] | number[],
|
||||
emptyFilter = false,
|
||||
inverseSelection = false,
|
||||
) => ({
|
||||
append_form_data: emptyFilter
|
||||
? {
|
||||
extras: {
|
||||
where: '1 = 0',
|
||||
},
|
||||
}
|
||||
: {
|
||||
filters:
|
||||
value === undefined || value === null || value.length === 0
|
||||
? []
|
||||
: [
|
||||
{
|
||||
col,
|
||||
op: inverseSelection ? ('NOT IN' as const) : ('IN' as const),
|
||||
val: value,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
export const getRangeExtraFormData = (
|
||||
col: string,
|
||||
lower?: number | null,
|
||||
upper?: number | null,
|
||||
) => {
|
||||
const filters: QueryObjectFilterClause[] = [];
|
||||
if (lower !== undefined && lower !== null) {
|
||||
filters.push({ col, op: '>=', val: lower });
|
||||
}
|
||||
if (upper !== undefined && upper !== null) {
|
||||
filters.push({ col, op: '<=', val: upper });
|
||||
}
|
||||
|
||||
return {
|
||||
append_form_data: {
|
||||
filters,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -60,10 +60,9 @@ import {
|
|||
EchartsTimeseriesChartPlugin,
|
||||
} from '@superset-ui/plugin-chart-echarts';
|
||||
import {
|
||||
AntdRangeFilterPlugin,
|
||||
AntdSelectFilterPlugin,
|
||||
} from '@superset-ui/plugin-filter-antd';
|
||||
|
||||
AntdRangeFilterPlugin,
|
||||
} from 'src/filters/components/';
|
||||
import FilterBoxChartPlugin from '../FilterBox/FilterBoxChartPlugin';
|
||||
import TimeTableChartPlugin from '../TimeTable/TimeTableChartPlugin';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue