From fecfc34cd3e3dd2efb8daee03d6416384914cc8a Mon Sep 17 00:00:00 2001 From: simchaNielsen <56388545+simchaNielsen@users.noreply.github.com> Date: Fri, 8 Jan 2021 14:44:25 +0200 Subject: [PATCH] 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> --- .../spec/javascripts/filters/utils_spec.ts | 156 ++++++++++++++++++ .../src/common/components/index.tsx | 1 + .../components/nativeFilters/FilterBar.tsx | 4 +- .../components/Range/AntdRangeFilter.tsx | 56 +++++++ .../filters/components/Range/buildQuery.ts | 74 +++++++++ .../filters/components/Range/controlPanel.ts | 44 +++++ .../components/Range/images/thumbnail.png | Bin 0 -> 5658 bytes .../src/filters/components/Range/index.ts | 42 +++++ .../components/Range/transformProps.ts | 33 ++++ .../src/filters/components/Range/types.ts | 39 +++++ .../components/Select/AntdSelectFilter.tsx | 94 +++++++++++ .../filters/components/Select/buildQuery.ts | 43 +++++ .../filters/components/Select/controlPanel.ts | 114 +++++++++++++ .../components/Select/images/thumbnail.png | Bin 0 -> 5658 bytes .../src/filters/components/Select/index.ts | 42 +++++ .../components/Select/transformProps.ts | 36 ++++ .../src/filters/components/Select/types.ts | 52 ++++++ .../src/filters/components/index.ts | 20 +++ .../src/filters/components/types.ts | 22 +++ superset-frontend/src/filters/utils.ts | 65 ++++++++ .../src/visualizations/presets/MainPreset.js | 5 +- 21 files changed, 937 insertions(+), 5 deletions(-) create mode 100644 superset-frontend/spec/javascripts/filters/utils_spec.ts create mode 100644 superset-frontend/src/filters/components/Range/AntdRangeFilter.tsx create mode 100644 superset-frontend/src/filters/components/Range/buildQuery.ts create mode 100644 superset-frontend/src/filters/components/Range/controlPanel.ts create mode 100644 superset-frontend/src/filters/components/Range/images/thumbnail.png create mode 100644 superset-frontend/src/filters/components/Range/index.ts create mode 100644 superset-frontend/src/filters/components/Range/transformProps.ts create mode 100644 superset-frontend/src/filters/components/Range/types.ts create mode 100644 superset-frontend/src/filters/components/Select/AntdSelectFilter.tsx create mode 100644 superset-frontend/src/filters/components/Select/buildQuery.ts create mode 100644 superset-frontend/src/filters/components/Select/controlPanel.ts create mode 100644 superset-frontend/src/filters/components/Select/images/thumbnail.png create mode 100644 superset-frontend/src/filters/components/Select/index.ts create mode 100644 superset-frontend/src/filters/components/Select/transformProps.ts create mode 100644 superset-frontend/src/filters/components/Select/types.ts create mode 100644 superset-frontend/src/filters/components/index.ts create mode 100644 superset-frontend/src/filters/components/types.ts create mode 100644 superset-frontend/src/filters/utils.ts diff --git a/superset-frontend/spec/javascripts/filters/utils_spec.ts b/superset-frontend/spec/javascripts/filters/utils_spec.ts new file mode 100644 index 000000000..453152b41 --- /dev/null +++ b/superset-frontend/spec/javascripts/filters/utils_spec.ts @@ -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: [], + }, + }); + }); + }); +}); diff --git a/superset-frontend/src/common/components/index.tsx b/superset-frontend/src/common/components/index.tsx index 632b52579..e193a2a28 100644 --- a/superset-frontend/src/common/components/index.tsx +++ b/superset-frontend/src/common/components/index.tsx @@ -44,6 +44,7 @@ export { Typography, Tree, Popover, + Slider, Radio, Row, Select, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar.tsx index 3361029ed..8e7d35475 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar.tsx @@ -222,7 +222,7 @@ const FilterValue: React.FC = ({ } = filter; const cascadingFilters = useCascadingFilters(id); const [loading, setLoading] = useState(true); - const [state, setState] = useState({ data: undefined }); + const [state, setState] = useState([]); const [formData, setFormData] = useState>({}); const [target] = targets; const { datasetId = 18, column } = target; @@ -256,7 +256,7 @@ const FilterValue: React.FC = ({ force: false, requestParams: { dashboardId: 0 }, }).then(response => { - setState({ data: response.result[0].data }); + setState(response.result); setLoading(false); }); } diff --git a/superset-frontend/src/filters/components/Range/AntdRangeFilter.tsx b/superset-frontend/src/filters/components/Range/AntdRangeFilter.tsx new file mode 100644 index 000000000..33c0f8341 --- /dev/null +++ b/superset-frontend/src/filters/components/Range/AntdRangeFilter.tsx @@ -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` + 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 ( + + + + ); +} diff --git a/superset-frontend/src/filters/components/Range/buildQuery.ts b/superset-frontend/src/filters/components/Range/buildQuery.ts new file mode 100644 index 000000000..1ea4fb12b --- /dev/null +++ b/superset-frontend/src/filters/components/Range/buildQuery.ts @@ -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', + }, + ], + }, + ]; + }); +} diff --git a/superset-frontend/src/filters/components/Range/controlPanel.ts b/superset-frontend/src/filters/components/Range/controlPanel.ts new file mode 100644 index 000000000..bfc1c09fd --- /dev/null +++ b/superset-frontend/src/filters/components/Range/controlPanel.ts @@ -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; diff --git a/superset-frontend/src/filters/components/Range/images/thumbnail.png b/superset-frontend/src/filters/components/Range/images/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..7afef30bd4e6e4f85723208bf9f429647d03d3e5 GIT binary patch literal 5658 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 literal 0 HcmV?d00001 diff --git a/superset-frontend/src/filters/components/Range/index.ts b/superset-frontend/src/filters/components/Range/index.ts new file mode 100644 index 000000000..4a77fbb97 --- /dev/null +++ b/superset-frontend/src/filters/components/Range/index.ts @@ -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, + }); + } +} diff --git a/superset-frontend/src/filters/components/Range/transformProps.ts b/superset-frontend/src/filters/components/Range/transformProps.ts new file mode 100644 index 000000000..ca9ec7f4a --- /dev/null +++ b/superset-frontend/src/filters/components/Range/transformProps.ts @@ -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, + }; +} diff --git a/superset-frontend/src/filters/components/Range/types.ts b/superset-frontend/src/filters/components/Range/types.ts new file mode 100644 index 000000000..63c9fbdce --- /dev/null +++ b/superset-frontend/src/filters/components/Range/types.ts @@ -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; +}; diff --git a/superset-frontend/src/filters/components/Select/AntdSelectFilter.tsx b/superset-frontend/src/filters/components/Select/AntdSelectFilter.tsx new file mode 100644 index 000000000..c29b6aa21 --- /dev/null +++ b/superset-frontend/src/filters/components/Select/AntdSelectFilter.tsx @@ -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` + 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 ( + + + + ); +} diff --git a/superset-frontend/src/filters/components/Select/buildQuery.ts b/superset-frontend/src/filters/components/Select/buildQuery.ts new file mode 100644 index 000000000..cc5447225 --- /dev/null +++ b/superset-frontend/src/filters/components/Select/buildQuery.ts @@ -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, + }, + ]; + }); +} diff --git a/superset-frontend/src/filters/components/Select/controlPanel.ts b/superset-frontend/src/filters/components/Select/controlPanel.ts new file mode 100644 index 000000000..2432396ca --- /dev/null +++ b/superset-frontend/src/filters/components/Select/controlPanel.ts @@ -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; diff --git a/superset-frontend/src/filters/components/Select/images/thumbnail.png b/superset-frontend/src/filters/components/Select/images/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..7afef30bd4e6e4f85723208bf9f429647d03d3e5 GIT binary patch literal 5658 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 literal 0 HcmV?d00001 diff --git a/superset-frontend/src/filters/components/Select/index.ts b/superset-frontend/src/filters/components/Select/index.ts new file mode 100644 index 000000000..f0d05c373 --- /dev/null +++ b/superset-frontend/src/filters/components/Select/index.ts @@ -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, + }); + } +} diff --git a/superset-frontend/src/filters/components/Select/transformProps.ts b/superset-frontend/src/filters/components/Select/transformProps.ts new file mode 100644 index 000000000..5888bb54d --- /dev/null +++ b/superset-frontend/src/filters/components/Select/transformProps.ts @@ -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, + }; +} diff --git a/superset-frontend/src/filters/components/Select/types.ts b/superset-frontend/src/filters/components/Select/types.ts new file mode 100644 index 000000000..bfa31170b --- /dev/null +++ b/superset-frontend/src/filters/components/Select/types.ts @@ -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, +}; diff --git a/superset-frontend/src/filters/components/index.ts b/superset-frontend/src/filters/components/index.ts new file mode 100644 index 000000000..fadaf1cde --- /dev/null +++ b/superset-frontend/src/filters/components/index.ts @@ -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'; diff --git a/superset-frontend/src/filters/components/types.ts b/superset-frontend/src/filters/components/types.ts new file mode 100644 index 000000000..869dc79e3 --- /dev/null +++ b/superset-frontend/src/filters/components/types.ts @@ -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; +} diff --git a/superset-frontend/src/filters/utils.ts b/superset-frontend/src/filters/utils.ts new file mode 100644 index 000000000..1a5d11ca2 --- /dev/null +++ b/superset-frontend/src/filters/utils.ts @@ -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, + }, + }; +}; diff --git a/superset-frontend/src/visualizations/presets/MainPreset.js b/superset-frontend/src/visualizations/presets/MainPreset.js index 48df2f366..0aec9ecbb 100644 --- a/superset-frontend/src/visualizations/presets/MainPreset.js +++ b/superset-frontend/src/visualizations/presets/MainPreset.js @@ -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';