Skip to content

Commit

Permalink
feat(Filter-sets): connect to api (#17055)
Browse files Browse the repository at this point in the history
* fix:fix get permission function

* feat: filtersets new

* feat: connect filter sets to api

* lint: fix lint

* doc: add comment
  • Loading branch information
simcha90 authored Oct 17, 2021
1 parent 40b88f0 commit 37944e1
Show file tree
Hide file tree
Showing 18 changed files with 316 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export const mockDataMaskInfo: DataMaskStateWithId = {

export const nativeFiltersInfo: NativeFiltersState = {
filterSets: {
'set-id': {
id: 'DefaultsID',
'1': {
id: 1,
name: 'Set name',
nativeFilters: {},
dataMask: mockDataMaskInfo,
Expand Down
1 change: 0 additions & 1 deletion superset-frontend/src/dashboard/actions/hydrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ export const hydrateDashboard = (dashboardData, chartData) => (

const nativeFilters = getInitialNativeFilterState({
filterConfig: metadata?.native_filter_configuration || [],
filterSetsConfig: metadata?.filter_sets_configuration || [],
});

if (!metadata) {
Expand Down
260 changes: 190 additions & 70 deletions superset-frontend/src/dashboard/actions/nativeFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,26 @@
import { makeApi } from '@superset-ui/core';
import { Dispatch } from 'redux';
import { FilterConfiguration } from 'src/dashboard/components/nativeFilters/types';
import { DataMaskType, DataMaskStateWithId } from 'src/dataMask/types';
import {
SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL,
setDataMaskForFilterConfigComplete,
} from 'src/dataMask/actions';
import { HYDRATE_DASHBOARD } from './hydrate';
import { dashboardInfoChanged } from './dashboardInfo';
import {
DashboardInfo,
Filters,
FilterSet,
FilterSetFullData,
FilterSets,
} from '../reducers/types';
import { DashboardInfo, RootState } from '../types';

export const SET_FILTER_CONFIG_BEGIN = 'SET_FILTER_CONFIG_BEGIN';
export interface SetFilterConfigBegin {
type: typeof SET_FILTER_CONFIG_BEGIN;
filterConfig: FilterConfiguration;
}

export const SET_FILTER_CONFIG_COMPLETE = 'SET_FILTER_CONFIG_COMPLETE';
export interface SetFilterConfigComplete {
type: typeof SET_FILTER_CONFIG_COMPLETE;
Expand All @@ -54,21 +55,60 @@ export interface SetInScopeStatusOfFilters {
type: typeof SET_IN_SCOPE_STATUS_OF_FILTERS;
filterConfig: FilterConfiguration;
}
export const SET_FILTER_SETS_CONFIG_BEGIN = 'SET_FILTER_SETS_CONFIG_BEGIN';
export interface SetFilterSetsConfigBegin {
type: typeof SET_FILTER_SETS_CONFIG_BEGIN;
filterSetsConfig: FilterSet[];
export const SET_FILTER_SETS_BEGIN = 'SET_FILTER_SETS_BEGIN';
export interface SetFilterSetsBegin {
type: typeof SET_FILTER_SETS_BEGIN;
}
export const SET_FILTER_SETS_COMPLETE = 'SET_FILTER_SETS_COMPLETE';
export interface SetFilterSetsComplete {
type: typeof SET_FILTER_SETS_COMPLETE;
filterSets: FilterSet[];
}
export const SET_FILTER_SETS_FAIL = 'SET_FILTER_SETS_FAIL';
export interface SetFilterSetsFail {
type: typeof SET_FILTER_SETS_FAIL;
}
export const SET_FILTER_SETS_CONFIG_COMPLETE =
'SET_FILTER_SETS_CONFIG_COMPLETE';
export interface SetFilterSetsConfigComplete {
type: typeof SET_FILTER_SETS_CONFIG_COMPLETE;
filterSetsConfig: FilterSet[];

export const CREATE_FILTER_SET_BEGIN = 'CREATE_FILTER_SET_BEGIN';
export interface CreateFilterSetBegin {
type: typeof CREATE_FILTER_SET_BEGIN;
}
export const CREATE_FILTER_SET_COMPLETE = 'CREATE_FILTER_SET_COMPLETE';
export interface CreateFilterSetComplete {
type: typeof CREATE_FILTER_SET_COMPLETE;
filterSet: FilterSet;
}
export const SET_FILTER_SETS_CONFIG_FAIL = 'SET_FILTER_SETS_CONFIG_FAIL';
export interface SetFilterSetsConfigFail {
type: typeof SET_FILTER_SETS_CONFIG_FAIL;
filterSetsConfig: FilterSet[];
export const CREATE_FILTER_SET_FAIL = 'CREATE_FILTER_SET_FAIL';
export interface CreateFilterSetFail {
type: typeof CREATE_FILTER_SET_FAIL;
}

export const DELETE_FILTER_SET_BEGIN = 'DELETE_FILTER_SET_BEGIN';
export interface DeleteFilterSetBegin {
type: typeof DELETE_FILTER_SET_BEGIN;
}
export const DELETE_FILTER_SET_COMPLETE = 'DELETE_FILTER_SET_COMPLETE';
export interface DeleteFilterSetComplete {
type: typeof DELETE_FILTER_SET_COMPLETE;
filterSet: FilterSet;
}
export const DELETE_FILTER_SET_FAIL = 'DELETE_FILTER_SET_FAIL';
export interface DeleteFilterSetFail {
type: typeof DELETE_FILTER_SET_FAIL;
}

export const UPDATE_FILTER_SET_BEGIN = 'UPDATE_FILTER_SET_BEGIN';
export interface UpdateFilterSetBegin {
type: typeof UPDATE_FILTER_SET_BEGIN;
}
export const UPDATE_FILTER_SET_COMPLETE = 'UPDATE_FILTER_SET_COMPLETE';
export interface UpdateFilterSetComplete {
type: typeof UPDATE_FILTER_SET_COMPLETE;
filterSet: FilterSet;
}
export const UPDATE_FILTER_SET_FAIL = 'UPDATE_FILTER_SET_FAIL';
export interface UpdateFilterSetFail {
type: typeof UPDATE_FILTER_SET_FAIL;
}

export const setFilterConfiguration = (
Expand Down Expand Up @@ -161,66 +201,138 @@ export interface SetBootstrapData {
data: BootstrapData;
}

export const setFilterSetsConfiguration = (
filterSetsConfig: FilterSet[],
) => async (dispatch: Dispatch, getState: () => any) => {
export const getFilterSets = () => async (
dispatch: Dispatch,
getState: () => RootState,
) => {
const dashboardId = getState().dashboardInfo.id;
const fetchFilterSets = makeApi<
null,
{
count: number;
ids: number[];
result: FilterSetFullData[];
}
>({
method: 'GET',
endpoint: `/api/v1/dashboard/${dashboardId}/filtersets`,
});

dispatch({
type: SET_FILTER_SETS_CONFIG_BEGIN,
filterSetsConfig,
type: SET_FILTER_SETS_BEGIN,
});
const { id, metadata } = getState().dashboardInfo;

// TODO extract this out when makeApi supports url parameters
const updateDashboard = makeApi<
Partial<DashboardInfo>,
{ result: DashboardInfo }
const response = await fetchFilterSets(null);

dispatch({
type: SET_FILTER_SETS_COMPLETE,
filterSets: response.ids.map((id, i) => ({
...response.result[i].params,
id,
name: response.result[i].name,
})),
});
};

export const createFilterSet = (filterSet: Omit<FilterSet, 'id'>) => async (
dispatch: Function,
getState: () => RootState,
) => {
const dashboardId = getState().dashboardInfo.id;
const postFilterSets = makeApi<
Partial<FilterSetFullData & { json_metadata: any }>,
{
count: number;
ids: number[];
result: FilterSetFullData[];
}
>({
method: 'PUT',
endpoint: `/api/v1/dashboard/${id}`,
method: 'POST',
endpoint: `/api/v1/dashboard/${dashboardId}/filtersets`,
});

try {
const response = await updateDashboard({
json_metadata: JSON.stringify({
...metadata,
filter_sets_configuration: filterSetsConfig,
}),
});
const newMetadata = JSON.parse(response.result.json_metadata);
dispatch(
dashboardInfoChanged({
metadata: newMetadata,
}),
);
dispatch({
type: SET_FILTER_SETS_CONFIG_COMPLETE,
filterSetsConfig: newMetadata?.filter_sets_configuration,
});
} catch (err) {
dispatch({ type: SET_FILTER_SETS_CONFIG_FAIL, filterSetsConfig });
}
dispatch({
type: CREATE_FILTER_SET_BEGIN,
});

const serverFilterSet: Omit<FilterSet, 'id' | 'name'> & { name?: string } = {
...filterSet,
};

delete serverFilterSet.name;

await postFilterSets({
name: filterSet.name,
owner_type: 'Dashboard',
owner_id: dashboardId,
json_metadata: JSON.stringify(serverFilterSet),
});

dispatch({
type: CREATE_FILTER_SET_COMPLETE,
});
dispatch(getFilterSets());
};

export const SAVE_FILTER_SETS = 'SAVE_FILTER_SETS';
export interface SaveFilterSets {
type: typeof SAVE_FILTER_SETS;
name: string;
dataMask: Pick<DataMaskStateWithId, DataMaskType.NativeFilters>;
filtersSetId: string;
}
export const updateFilterSet = (filterSet: FilterSet) => async (
dispatch: Function,
getState: () => RootState,
) => {
const dashboardId = getState().dashboardInfo.id;
const postFilterSets = makeApi<
Partial<FilterSetFullData & { json_metadata: any }>,
{}
>({
method: 'PUT',
endpoint: `/api/v1/dashboard/${dashboardId}/filtersets/${filterSet.id}`,
});

export function saveFilterSets(
name: string,
filtersSetId: string,
dataMask: Pick<DataMaskStateWithId, DataMaskType.NativeFilters>,
): SaveFilterSets {
return {
type: SAVE_FILTER_SETS,
name,
filtersSetId,
dataMask,
dispatch({
type: UPDATE_FILTER_SET_BEGIN,
});

const serverFilterSet: Omit<FilterSet, 'id' | 'name'> & {
name?: string;
id?: number;
} = {
...filterSet,
};
}

delete serverFilterSet.id;
delete serverFilterSet.name;

await postFilterSets({
name: filterSet.name,
json_metadata: JSON.stringify(serverFilterSet),
});

dispatch({
type: UPDATE_FILTER_SET_COMPLETE,
});
dispatch(getFilterSets());
};

export const deleteFilterSet = (filterSetId: number) => async (
dispatch: Function,
getState: () => RootState,
) => {
const dashboardId = getState().dashboardInfo.id;
const deleteFilterSets = makeApi<{}, {}>({
method: 'DELETE',
endpoint: `/api/v1/dashboard/${dashboardId}/filtersets/${filterSetId}`,
});

dispatch({
type: DELETE_FILTER_SET_BEGIN,
});

await deleteFilterSets({});

dispatch({
type: DELETE_FILTER_SET_COMPLETE,
});
dispatch(getFilterSets());
};

export const SET_FOCUSED_NATIVE_FILTER = 'SET_FOCUSED_NATIVE_FILTER';
export interface SetFocusedNativeFilter {
Expand Down Expand Up @@ -248,11 +360,19 @@ export type AnyFilterAction =
| SetFilterConfigBegin
| SetFilterConfigComplete
| SetFilterConfigFail
| SetFilterSetsConfigBegin
| SetFilterSetsConfigComplete
| SetFilterSetsConfigFail
| SetFilterSetsBegin
| SetFilterSetsComplete
| SetFilterSetsFail
| SetInScopeStatusOfFilters
| SaveFilterSets
| SetBootstrapData
| SetFocusedNativeFilter
| UnsetFocusedNativeFilter;
| UnsetFocusedNativeFilter
| CreateFilterSetBegin
| CreateFilterSetComplete
| CreateFilterSetFail
| DeleteFilterSetBegin
| DeleteFilterSetComplete
| DeleteFilterSetFail
| UpdateFilterSetBegin
| UpdateFilterSetComplete
| UpdateFilterSetFail;
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { Provider } from 'react-redux';
import EditSection, { EditSectionProps } from './EditSection';

const createProps = () => ({
filterSetId: 'set-id',
filterSetId: 1,
dataMaskSelected: {
DefaultsID: {
filterState: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { HandlerFunction, styled, t } from '@superset-ui/core';
import { Typography, Tooltip } from 'src/common/components';
import { useDispatch } from 'react-redux';
import Button from 'src/components/Button';
import { setFilterSetsConfiguration } from 'src/dashboard/actions/nativeFilters';
import { updateFilterSet } from 'src/dashboard/actions/nativeFilters';
import { DataMaskState } from 'src/dataMask/types';
import { WarningOutlined } from '@ant-design/icons';
import { ActionButtons } from './Footer';
Expand Down Expand Up @@ -60,7 +60,7 @@ const ActionButton = styled.div<{ disabled?: boolean }>`
`;

export type EditSectionProps = {
filterSetId: string;
filterSetId: number;
dataMaskSelected: DataMaskState;
onCancel: HandlerFunction;
disabled: boolean;
Expand Down Expand Up @@ -89,17 +89,12 @@ const EditSection: FC<EditSectionProps> = ({

const handleSave = () => {
dispatch(
setFilterSetsConfiguration(
filterSetFilterValues.map(filterSet => {
const newFilterSet = {
...filterSet,
name: filterSetName,
nativeFilters: filters,
dataMask: { ...dataMaskApplied },
};
return filterSetId === filterSet.id ? newFilterSet : filterSet;
}),
),
updateFilterSet({
id: filterSetId,
name: filterSetName,
nativeFilters: filters,
dataMask: { ...dataMaskApplied },
}),
);
onCancel();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import { render, screen } from 'spec/helpers/testing-library';
import { mockStore } from 'spec/fixtures/mockStore';
import { Provider } from 'react-redux';
import FilterSets, { FilterSetsProps } from '.';
import { TabIds } from '../utils';

const createProps = () => ({
disabled: false,
isFilterSetChanged: false,
tab: TabIds.FilterSets,
dataMaskSelected: {
DefaultsID: {
filterState: {
Expand Down
Loading

0 comments on commit 37944e1

Please sign in to comment.