This is an automated email from the ASF dual-hosted git repository.
amitmiran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 13d4902 feat(native-filters): select group by support (#14217)
13d4902 is described below
commit 13d490271130810d7cf0b3eafc56ba71eeba66c0
Author: Amit Miran <[email protected]>
AuthorDate: Tue Apr 20 18:52:33 2021 +0300
feat(native-filters): select group by support (#14217)
* chore: initial commit
* feat: groupby filter
Co-authored-by: Simcha Shats <[email protected]>
---
.../FiltersConfigForm/FiltersConfigForm.tsx | 7 +-
.../components/GroupBy/GroupByFilterPlugin.tsx | 86 +++++++++++++++++++++
.../src/filters/components/GroupBy/buildQuery.ts | 45 +++++++++++
.../src/filters/components/GroupBy/controlPanel.ts | 51 ++++++++++++
.../components/GroupBy/images/thumbnail.png | Bin 0 -> 5658 bytes
.../src/filters/components/{ => GroupBy}/index.ts | 29 +++++--
.../{index.ts => GroupBy/transformProps.ts} | 32 ++++++--
.../src/filters/components/GroupBy/types.ts | 50 ++++++++++++
superset-frontend/src/filters/components/index.ts | 1 +
.../src/visualizations/presets/MainPreset.js | 2 +
10 files changed, 292 insertions(+), 11 deletions(-)
diff --git
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
index 0a9ba42..b11d356 100644
---
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
+++
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
@@ -79,7 +79,12 @@ export interface FiltersConfigFormProps {
parentFilters: { id: string; title: string }[];
}
-const FILTERS_WITHOUT_COLUMN = ['filter_timegrain', 'filter_timecolumn'];
+// TODO: Need to do with it something
+const FILTERS_WITHOUT_COLUMN = [
+ 'filter_timegrain',
+ 'filter_timecolumn',
+ 'filter_groupby',
+];
/**
* The configuration form for a specific filter.
diff --git
a/superset-frontend/src/filters/components/GroupBy/GroupByFilterPlugin.tsx
b/superset-frontend/src/filters/components/GroupBy/GroupByFilterPlugin.tsx
new file mode 100644
index 0000000..3440090
--- /dev/null
+++ b/superset-frontend/src/filters/components/GroupBy/GroupByFilterPlugin.tsx
@@ -0,0 +1,86 @@
+/**
+ * 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 { ensureIsArray, ExtraFormData, t, tn } from '@superset-ui/core';
+import React, { useEffect, useState } from 'react';
+import { Select } from 'src/common/components';
+import { Styles, StyledSelect } from '../common';
+import { PluginFilterGroupByProps } from './types';
+
+const { Option } = Select;
+
+export default function PluginFilterGroupBy(props: PluginFilterGroupByProps) {
+ const { data, formData, height, width, setDataMask, filterState } = props;
+ const { defaultValue, inputRef, multiSelect } = formData;
+
+ const [value, setValue] = useState<string[]>(defaultValue ?? []);
+
+ const handleChange = (value?: string[] | string | null) => {
+ const resultValue: string[] = ensureIsArray<string>(value);
+ setValue(resultValue);
+ const extraFormData: ExtraFormData = {};
+ if (resultValue.length) {
+ extraFormData.interactive_groupby = resultValue;
+ }
+
+ setDataMask({
+ filterState: { value: resultValue.length ? resultValue : null },
+ extraFormData,
+ });
+ };
+
+ useEffect(() => {
+ handleChange(filterState.value);
+ }, [JSON.stringify(filterState.value), multiSelect]);
+
+ useEffect(() => {
+ handleChange(defaultValue ?? null);
+ // I think after Config Modal update some filter it re-creates default
value for all other filters
+ // so we can process it like this `JSON.stringify` or start to use `Immer`
+ }, [JSON.stringify(defaultValue), multiSelect]);
+
+ const columns = data || [];
+ const placeholderText =
+ columns.length === 0
+ ? t('No columns')
+ : tn('%s option', '%s options', columns.length, columns.length);
+ return (
+ <Styles height={height} width={width}>
+ <StyledSelect
+ allowClear
+ value={value}
+ placeholder={placeholderText}
+ mode={multiSelect ? 'multiple' : undefined}
+ // @ts-ignore
+ onChange={handleChange}
+ ref={inputRef}
+ >
+ {columns.map(
+ (row: { column_name: string; verbose_name: string | null }) => {
+ const { column_name: columnName, verbose_name: verboseName } = row;
+ return (
+ <Option key={columnName} value={columnName}>
+ {verboseName ?? columnName}
+ </Option>
+ );
+ },
+ )}
+ </StyledSelect>
+ </Styles>
+ );
+}
diff --git a/superset-frontend/src/filters/components/GroupBy/buildQuery.ts
b/superset-frontend/src/filters/components/GroupBy/buildQuery.ts
new file mode 100644
index 0000000..b6ca68a
--- /dev/null
+++ b/superset-frontend/src/filters/components/GroupBy/buildQuery.ts
@@ -0,0 +1,45 @@
+/**
+ * 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 => [
+ {
+ ...baseQueryObject,
+ result_type: 'columns',
+ columns: [],
+ metrics: [],
+ orderby: [],
+ },
+ ]);
+}
diff --git a/superset-frontend/src/filters/components/GroupBy/controlPanel.ts
b/superset-frontend/src/filters/components/GroupBy/controlPanel.ts
new file mode 100644
index 0000000..33922d0
--- /dev/null
+++ b/superset-frontend/src/filters/components/GroupBy/controlPanel.ts
@@ -0,0 +1,51 @@
+/**
+ * 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 { ControlPanelConfig, sections } from '@superset-ui/chart-controls';
+import { t } from '@superset-ui/core';
+import { DEFAULT_FORM_DATA } from './types';
+
+const { multiSelect } = DEFAULT_FORM_DATA;
+
+const config: ControlPanelConfig = {
+ controlPanelSections: [
+ // @ts-ignore
+ sections.legacyRegularTime,
+ {
+ label: t('UI Configuration'),
+ expanded: true,
+ controlSetRows: [
+ [
+ {
+ name: 'multiSelect',
+ config: {
+ type: 'CheckboxControl',
+ label: t('Multiple select'),
+ default: multiSelect,
+ resetConfig: true,
+ renderTrigger: true,
+ description: t('Allow selecting multiple values'),
+ },
+ },
+ ],
+ ],
+ },
+ ],
+};
+
+export default config;
diff --git
a/superset-frontend/src/filters/components/GroupBy/images/thumbnail.png
b/superset-frontend/src/filters/components/GroupBy/images/thumbnail.png
new file mode 100644
index 0000000..7afef30
Binary files /dev/null and
b/superset-frontend/src/filters/components/GroupBy/images/thumbnail.png differ
diff --git a/superset-frontend/src/filters/components/index.ts
b/superset-frontend/src/filters/components/GroupBy/index.ts
similarity index 53%
copy from superset-frontend/src/filters/components/index.ts
copy to superset-frontend/src/filters/components/GroupBy/index.ts
index 662b7a8..44055fa 100644
--- a/superset-frontend/src/filters/components/index.ts
+++ b/superset-frontend/src/filters/components/GroupBy/index.ts
@@ -16,8 +16,27 @@
* specific language governing permissions and limitations
* under the License.
*/
-export { default as SelectFilterPlugin } from './Select';
-export { default as RangeFilterPlugin } from './Range';
-export { default as TimeFilterPlugin } from './Time';
-export { default as TimeColumnFilterPlugin } from './TimeColumn';
-export { default as TimeGrainFilterPlugin } from './TimeGrain';
+import { Behavior, ChartMetadata, ChartPlugin, t } 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 FilterGroupByPlugin extends ChartPlugin {
+ constructor() {
+ const metadata = new ChartMetadata({
+ name: t('Group By'),
+ description: t('Group By filter plugin'),
+ behaviors: [Behavior.INTERACTIVE_CHART, Behavior.NATIVE_FILTER],
+ thumbnail,
+ });
+
+ super({
+ buildQuery,
+ controlPanel,
+ loadChart: () => import('./GroupByFilterPlugin'),
+ metadata,
+ transformProps,
+ });
+ }
+}
diff --git a/superset-frontend/src/filters/components/index.ts
b/superset-frontend/src/filters/components/GroupBy/transformProps.ts
similarity index 60%
copy from superset-frontend/src/filters/components/index.ts
copy to superset-frontend/src/filters/components/GroupBy/transformProps.ts
index 662b7a8..ee075bb 100644
--- a/superset-frontend/src/filters/components/index.ts
+++ b/superset-frontend/src/filters/components/GroupBy/transformProps.ts
@@ -16,8 +16,30 @@
* specific language governing permissions and limitations
* under the License.
*/
-export { default as SelectFilterPlugin } from './Select';
-export { default as RangeFilterPlugin } from './Range';
-export { default as TimeFilterPlugin } from './Time';
-export { default as TimeColumnFilterPlugin } from './TimeColumn';
-export { default as TimeGrainFilterPlugin } from './TimeGrain';
+import { ChartProps } from '@superset-ui/core';
+import { DEFAULT_FORM_DATA } from './types';
+
+export default function transformProps(chartProps: ChartProps) {
+ const {
+ behaviors,
+ formData,
+ height,
+ hooks,
+ queriesData,
+ width,
+ filterState,
+ } = chartProps;
+ const { setDataMask = () => {} } = hooks;
+
+ const { data } = queriesData[0];
+
+ return {
+ filterState,
+ behaviors,
+ width,
+ height,
+ data,
+ formData: { ...DEFAULT_FORM_DATA, ...formData },
+ setDataMask,
+ };
+}
diff --git a/superset-frontend/src/filters/components/GroupBy/types.ts
b/superset-frontend/src/filters/components/GroupBy/types.ts
new file mode 100644
index 0000000..7b8ae7a
--- /dev/null
+++ b/superset-frontend/src/filters/components/GroupBy/types.ts
@@ -0,0 +1,50 @@
+/**
+ * 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 {
+ Behavior,
+ DataRecord,
+ FilterState,
+ QueryFormData,
+ SetDataMaskHook,
+} from '@superset-ui/core';
+import { RefObject } from 'react';
+import { PluginFilterStylesProps } from '../types';
+
+interface PluginFilterGroupByCustomizeProps {
+ defaultValue?: string[] | null;
+ inputRef?: RefObject<HTMLInputElement>;
+ multiSelect: boolean;
+}
+
+export type PluginFilterGroupByQueryFormData = QueryFormData &
+ PluginFilterStylesProps &
+ PluginFilterGroupByCustomizeProps;
+
+export type PluginFilterGroupByProps = PluginFilterStylesProps & {
+ behaviors: Behavior[];
+ data: DataRecord[];
+ setDataMask: SetDataMaskHook;
+ filterState: FilterState;
+ formData: PluginFilterGroupByQueryFormData;
+};
+
+export const DEFAULT_FORM_DATA: PluginFilterGroupByCustomizeProps = {
+ defaultValue: null,
+ multiSelect: false,
+};
diff --git a/superset-frontend/src/filters/components/index.ts
b/superset-frontend/src/filters/components/index.ts
index 662b7a8..11ad1a4 100644
--- a/superset-frontend/src/filters/components/index.ts
+++ b/superset-frontend/src/filters/components/index.ts
@@ -20,4 +20,5 @@ export { default as SelectFilterPlugin } from './Select';
export { default as RangeFilterPlugin } from './Range';
export { default as TimeFilterPlugin } from './Time';
export { default as TimeColumnFilterPlugin } from './TimeColumn';
+export { default as GroupByFilterPlugin } from './GroupBy';
export { default as TimeGrainFilterPlugin } from './TimeGrain';
diff --git a/superset-frontend/src/visualizations/presets/MainPreset.js
b/superset-frontend/src/visualizations/presets/MainPreset.js
index 77cfdce..02c5414 100644
--- a/superset-frontend/src/visualizations/presets/MainPreset.js
+++ b/superset-frontend/src/visualizations/presets/MainPreset.js
@@ -68,6 +68,7 @@ import {
TimeFilterPlugin,
TimeColumnFilterPlugin,
TimeGrainFilterPlugin,
+ GroupByFilterPlugin,
} from 'src/filters/components/';
import { PivotTableChartPlugin as PivotTableChartPluginV2 } from
'@superset-ui/plugin-chart-pivot-table';
import FilterBoxChartPlugin from '../FilterBox/FilterBoxChartPlugin';
@@ -129,6 +130,7 @@ export default class MainPreset extends Preset {
new TimeFilterPlugin().configure({ key: 'filter_time' }),
new TimeColumnFilterPlugin().configure({ key: 'filter_timecolumn' }),
new TimeGrainFilterPlugin().configure({ key: 'filter_timegrain' }),
+ new GroupByFilterPlugin().configure({ key: 'filter_groupby' }),
],
});
}