feat(native-filters): add refresh button to default value picker (#14375)
* feat(native-filters): add refresh button to default value picker
* skip flaky test
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 776e1e9..d1cabf9b 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
@@ -17,13 +17,14 @@
* under the License.
*/
import {
- styled,
- t,
- getChartMetadataRegistry,
- Behavior,
AdhocFilter,
+ Behavior,
+ ChartDataResponseResult,
+ getChartMetadataRegistry,
JsonResponse,
+ styled,
SupersetApiError,
+ t,
} from '@superset-ui/core';
import { ColumnMeta, DatasourceMeta } from '@superset-ui/chart-controls';
import { FormInstance } from 'antd/lib/form';
@@ -38,6 +39,10 @@
import DateFilterControl from 'src/explore/components/controls/DateFilterControl';
import { addDangerToast } from 'src/messageToasts/actions';
import { ClientErrorObject } from 'src/utils/getClientErrorObject';
+import Button from 'src/components/Button';
+import { getChartDataRequest } from 'src/chart/chartAction';
+import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
+import { waitForAsyncData } from 'src/middleware/asyncEvent';
import { ColumnSelect } from './ColumnSelect';
import { NativeFiltersForm } from '../types';
import {
@@ -111,8 +116,22 @@
parentFilters,
}) => {
const forceUpdate = useForceUpdate();
- const formFilter = (form.getFieldValue('filters') || {})[filterId];
const [datasetDetails, setDatasetDetails] = useState<Record<string, any>>();
+
+ // make sure the formFilter is populated
+ if (!form.getFieldValue('filters')) {
+ setNativeFilterFieldValues(form, filterId, filterToEdit || {});
+ forceUpdate();
+ }
+ const formFilter = form.getFieldValue('filters')[filterId];
+
+ useEffect(() => {
+ setNativeFilterFieldValues(form, filterId, {
+ defaultValue: filterToEdit?.defaultValue,
+ });
+ forceUpdate();
+ }, [form, forceUpdate, filterId, filterToEdit?.defaultValue]);
+
const nativeFilterItems = getChartMetadataRegistry().items;
const nativeFilterVizTypes = Object.entries(nativeFilterItems)
// @ts-ignore
@@ -158,7 +177,56 @@
formFilter?.filterType,
);
- useBackendFormUpdate(form, filterId, filterToEdit, hasDataset, hasColumn);
+ const isDataDirty = formFilter?.isDataDirty ?? true;
+
+ useBackendFormUpdate(form, filterId);
+
+ const refreshHandler = () => {
+ if (!hasDataset || !formFilter?.dataset?.value) {
+ forceUpdate();
+ return;
+ }
+ const formData = getFormData({
+ datasetId: formFilter?.dataset?.value,
+ groupby: formFilter?.column,
+ defaultValue: formFilter?.defaultValue,
+ ...formFilter,
+ });
+ setNativeFilterFieldValues(form, filterId, {
+ defaultValueQueriesData: null,
+ isDataDirty: false,
+ });
+ forceUpdate();
+ getChartDataRequest({
+ formData,
+ force: false,
+ requestParams: { dashboardId: 0 },
+ }).then(response => {
+ if (isFeatureEnabled(FeatureFlag.GLOBAL_ASYNC_QUERIES)) {
+ // deal with getChartDataRequest transforming the response data
+ const result = 'result' in response ? response.result[0] : response;
+ waitForAsyncData(result)
+ .then((asyncResult: ChartDataResponseResult[]) => {
+ setNativeFilterFieldValues(form, filterId, {
+ defaultValueQueriesData: asyncResult,
+ });
+ forceUpdate();
+ })
+ .catch((error: ClientErrorObject) => {
+ // TODO: show error once this logic is moved into new NativeFilter
+ // component
+ console.error(
+ error.message || error.error || t('Check configuration'),
+ );
+ });
+ } else {
+ setNativeFilterFieldValues(form, filterId, {
+ defaultValueQueriesData: response.result,
+ });
+ forceUpdate();
+ }
+ });
+ };
const defaultDatasetSelectOptions = Object.values(loadedDatasets).map(
datasetToSelectOption,
@@ -254,6 +322,7 @@
// We need reset column when dataset changed
if (datasetId && e?.value !== datasetId) {
setNativeFilterFieldValues(form, filterId, {
+ defaultValue: null,
column: null,
});
}
@@ -275,7 +344,13 @@
form={form}
filterId={filterId}
datasetId={datasetId}
- onChange={forceUpdate}
+ onChange={e => {
+ // We need reset default value when when column changed
+ setNativeFilterFieldValues(form, filterId, {
+ defaultValue: null,
+ });
+ forceUpdate();
+ }}
/>
</StyledFormItem>
)}
@@ -347,27 +422,36 @@
isClearable
/>
</StyledFormItem>
- <StyledFormItem
- name={['filters', filterId, 'defaultValue']}
- initialValue={filterToEdit?.defaultValue}
- data-test="default-input"
- label={<StyledLabel>{t('Default Value')}</StyledLabel>}
- >
- {(hasFilledDataset || !hasDataset) && (
- <DefaultValue
- setDataMask={({ filterState }) => {
- setNativeFilterFieldValues(form, filterId, {
- defaultValue: filterState?.value,
- });
- forceUpdate();
- }}
- filterId={filterId}
- hasDataset={hasDataset}
- form={form}
- formData={newFormData}
- />
- )}
- </StyledFormItem>
+ <StyledContainer>
+ <StyledFormItem className="bottom" label={<StyledLabel />}>
+ {hasDataset && hasFilledDataset && (
+ <Button onClick={refreshHandler}>
+ {isDataDirty ? t('Populate') : t('Refresh')}
+ </Button>
+ )}
+ </StyledFormItem>
+ <StyledFormItem
+ name={['filters', filterId, 'defaultValue']}
+ initialValue={filterToEdit?.defaultValue}
+ data-test="default-input"
+ label={<StyledLabel>{t('Default Value')}</StyledLabel>}
+ >
+ {!isDataDirty && (hasFilledDataset || !hasDataset) && (
+ <DefaultValue
+ setDataMask={({ filterState }) => {
+ setNativeFilterFieldValues(form, filterId, {
+ defaultValue: filterState?.value,
+ });
+ forceUpdate();
+ }}
+ filterId={filterId}
+ hasDataset={hasDataset}
+ form={form}
+ formData={newFormData}
+ />
+ )}
+ </StyledFormItem>
+ </StyledContainer>
<StyledCheckboxFormItem
name={['filters', filterId, 'isInstant']}
initialValue={filterToEdit?.isInstant || false}
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
index c48076f..2ade134 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
@@ -18,102 +18,38 @@
*/
import { useEffect } from 'react';
import { FormInstance } from 'antd/lib/form';
-import { getChartDataRequest } from 'src/chart/chartAction';
-import { ChartDataResponseResult, t } from '@superset-ui/core';
-import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
-import { waitForAsyncData } from 'src/middleware/asyncEvent';
-import { ClientErrorObject } from 'src/utils/getClientErrorObject';
import { NativeFiltersForm } from '../types';
import { setNativeFilterFieldValues, useForceUpdate } from './utils';
-import { Filter } from '../../types';
-import { getFormData } from '../../utils';
// When some fields in form changed we need re-fetch data for Filter defaultValue
// eslint-disable-next-line import/prefer-default-export
export const useBackendFormUpdate = (
form: FormInstance<NativeFiltersForm>,
filterId: string,
- filterToEdit?: Filter,
- hasDatasource?: boolean,
- hasColumn?: boolean,
) => {
const forceUpdate = useForceUpdate();
const formFilter = (form.getFieldValue('filters') || {})[filterId];
useEffect(() => {
- let resolvedDefaultValue: any = null;
- if (!hasDatasource) {
- forceUpdate();
- return;
- }
- // No need to check data set change because it cascading update column
- // So check that column exists is enough
- if (hasColumn && !formFilter?.column) {
- setNativeFilterFieldValues(form, filterId, {
- defaultValueQueriesData: [],
- defaultValue: resolvedDefaultValue,
- });
- return;
- }
- if (!formFilter?.dataset?.value) {
- // no need to make chart data request if no dataset is defined
- return;
- }
- const formData = getFormData({
- datasetId: formFilter?.dataset?.value,
- groupby: formFilter?.column,
- defaultValue: formFilter?.defaultValue,
- ...formFilter,
- });
setNativeFilterFieldValues(form, filterId, {
+ isDataDirty: true,
defaultValueQueriesData: null,
- defaultValue: resolvedDefaultValue,
});
forceUpdate();
- getChartDataRequest({
- formData,
- force: false,
- requestParams: { dashboardId: 0 },
- }).then(response => {
- if (
- filterToEdit?.filterType === formFilter?.filterType &&
- filterToEdit?.targets[0].datasetId === formFilter?.dataset?.value &&
- (!hasColumn ||
- formFilter?.column === filterToEdit?.targets[0].column?.name)
- ) {
- resolvedDefaultValue = filterToEdit?.defaultValue;
- }
- if (isFeatureEnabled(FeatureFlag.GLOBAL_ASYNC_QUERIES)) {
- // deal with getChartDataRequest transforming the response data
- const result = 'result' in response ? response.result[0] : response;
- waitForAsyncData(result)
- .then((asyncResult: ChartDataResponseResult[]) => {
- setNativeFilterFieldValues(form, filterId, {
- defaultValueQueriesData: asyncResult,
- defaultValue: resolvedDefaultValue,
- });
- forceUpdate();
- })
- .catch((error: ClientErrorObject) => {
- // TODO: show error once this logic is moved into new NativeFilter
- // component
- console.error(
- error.message || error.error || t('Check configuration'),
- );
- });
- } else {
- setNativeFilterFieldValues(form, filterId, {
- defaultValueQueriesData: response.result,
- defaultValue: resolvedDefaultValue,
- });
- forceUpdate();
- }
- });
}, [
+ form,
formFilter?.filterType,
formFilter?.column,
formFilter?.dataset?.value,
JSON.stringify(formFilter?.adhoc_filters),
formFilter?.time_range,
+ forceUpdate,
filterId,
]);
+
+ useEffect(() => {
+ setNativeFilterFieldValues(form, filterId, {
+ defaultValue: formFilter?.defaultValue,
+ });
+ forceUpdate();
+ }, [form, formFilter?.defaultValue, forceUpdate, filterId]);
};
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils.ts
index 015a2f1..61ef409 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils.ts
@@ -31,7 +31,7 @@
filterId: string,
values: object,
) => {
- const formFilters = form.getFieldValue('filters');
+ const formFilters = form.getFieldValue('filters') || {};
form.setFieldsValue({
filters: {
...formFilters,