refactor: Unify shared datasources reducers and actions (#20645)

* refactor: Unify shared datasources reducers and actions

* Removes column_types

* Adjusts hydrateExplore

* Revert "Removes column_types"

This reverts commit 096bbf7826.

* Fixes test
This commit is contained in:
Michael S. Molina 2022-07-13 13:03:36 -03:00 committed by GitHub
parent ec2eb3ddf8
commit 2a705406e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 90 additions and 259 deletions

View File

@ -28,6 +28,7 @@ import type {
QueryFormData, QueryFormData,
QueryFormMetric, QueryFormMetric,
QueryResponse, QueryResponse,
GenericDataType,
} from '@superset-ui/core'; } from '@superset-ui/core';
import { sharedControls } from './shared-controls'; import { sharedControls } from './shared-controls';
import sharedControlComponents from './shared-controls/components'; import sharedControlComponents from './shared-controls/components';
@ -66,6 +67,7 @@ export interface Dataset {
id: number; id: number;
type: DatasourceType; type: DatasourceType;
columns: ColumnMeta[]; columns: ColumnMeta[];
column_types?: GenericDataType[];
metrics: Metric[]; metrics: Metric[];
column_format: Record<string, string>; column_format: Record<string, string>;
verbose_map: Record<string, string>; verbose_map: Record<string, string>;
@ -79,6 +81,7 @@ export interface Dataset {
description: string | null; description: string | null;
uid?: string; uid?: string;
owners?: Owner[]; owners?: Owner[];
table_name?: string;
} }
export interface ControlPanelState { export interface ControlPanelState {

View File

@ -22,7 +22,7 @@ import dashboardInfo from 'src/dashboard/reducers/dashboardInfo';
import dashboardState from 'src/dashboard/reducers/dashboardState'; import dashboardState from 'src/dashboard/reducers/dashboardState';
import dashboardFilters from 'src/dashboard/reducers/dashboardFilters'; import dashboardFilters from 'src/dashboard/reducers/dashboardFilters';
import nativeFilters from 'src/dashboard/reducers/nativeFilters'; import nativeFilters from 'src/dashboard/reducers/nativeFilters';
import datasources from 'src/dashboard/reducers/datasources'; import datasources from 'src/datasource/reducer';
import sliceEntities from 'src/dashboard/reducers/sliceEntities'; import sliceEntities from 'src/dashboard/reducers/sliceEntities';
import dashboardLayout from 'src/dashboard/reducers/undoableDashboardLayout'; import dashboardLayout from 'src/dashboard/reducers/undoableDashboardLayout';
import messageToasts from 'src/components/MessageToasts/reducers'; import messageToasts from 'src/components/MessageToasts/reducers';

View File

@ -19,7 +19,7 @@
/* eslint camelcase: 0 */ /* eslint camelcase: 0 */
import { t } from '@superset-ui/core'; import { t } from '@superset-ui/core';
import { HYDRATE_DASHBOARD } from 'src/dashboard/actions/hydrate'; import { HYDRATE_DASHBOARD } from 'src/dashboard/actions/hydrate';
import { DatasourcesAction } from 'src/dashboard/actions/datasources'; import { DatasourcesActionType } from 'src/datasource/actions';
import { ChartState } from 'src/explore/types'; import { ChartState } from 'src/explore/types';
import { getFormDataFromControls } from 'src/explore/controlUtils'; import { getFormDataFromControls } from 'src/explore/controlUtils';
import { HYDRATE_EXPLORE } from 'src/explore/actions/hydrateExplore'; import { HYDRATE_EXPLORE } from 'src/explore/actions/hydrateExplore';
@ -198,7 +198,7 @@ export default function chartReducer(
if (action.type === HYDRATE_DASHBOARD || action.type === HYDRATE_EXPLORE) { if (action.type === HYDRATE_DASHBOARD || action.type === HYDRATE_EXPLORE) {
return { ...action.data.charts }; return { ...action.data.charts };
} }
if (action.type === DatasourcesAction.SET_DATASOURCES) { if (action.type === DatasourcesActionType.SET_DATASOURCES) {
return Object.fromEntries( return Object.fromEntries(
Object.entries(charts).map(([chartId, chart]) => [ Object.entries(charts).map(([chartId, chart]) => [
chartId, chartId,

View File

@ -43,13 +43,13 @@ import serializeFilterScopes from 'src/dashboard/util/serializeFilterScopes';
import { getActiveFilters } from 'src/dashboard/util/activeDashboardFilters'; import { getActiveFilters } from 'src/dashboard/util/activeDashboardFilters';
import { safeStringify } from 'src/utils/safeStringify'; import { safeStringify } from 'src/utils/safeStringify';
import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags'; import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
import { fetchDatasourceMetadata } from 'src/dashboard/util/fetchDatasourceMetadata';
import { UPDATE_COMPONENTS_PARENTS_LIST } from './dashboardLayout'; import { UPDATE_COMPONENTS_PARENTS_LIST } from './dashboardLayout';
import { import {
setChartConfiguration, setChartConfiguration,
dashboardInfoChanged, dashboardInfoChanged,
SET_CHART_CONFIG_COMPLETE, SET_CHART_CONFIG_COMPLETE,
} from './dashboardInfo'; } from './dashboardInfo';
import { fetchDatasourceMetadata } from './datasources';
import { import {
addFilter, addFilter,
removeFilter, removeFilter,

View File

@ -88,9 +88,7 @@ export const datasetToSelectOption = (
// TODO: add column_types field to Dataset // TODO: add column_types field to Dataset
// We return true if column_types is undefined or empty as a precaution against backend failing to return column_types // We return true if column_types is undefined or empty as a precaution against backend failing to return column_types
export const hasTemporalColumns = ( export const hasTemporalColumns = (dataset: Dataset) => {
dataset: Dataset & { column_types: GenericDataType[] },
) => {
const columnTypes = ensureIsArray(dataset?.column_types); const columnTypes = ensureIsArray(dataset?.column_types);
return ( return (
columnTypes.length === 0 || columnTypes.includes(GenericDataType.TEMPORAL) columnTypes.length === 0 || columnTypes.includes(GenericDataType.TEMPORAL)

View File

@ -1,6 +1,6 @@
/* eslint-disable import/prefer-default-export */ /* eslint-disable import/prefer-default-export */
import { DatasourceType } from '@superset-ui/core'; import { DatasourceType } from '@superset-ui/core';
import { Datasource } from 'src/dashboard/types'; import { Dataset } from '@superset-ui/chart-controls';
/** /**
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file * or more contributor license agreements. See the NOTICE file
@ -19,7 +19,7 @@ import { Datasource } from 'src/dashboard/types';
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
export const PLACEHOLDER_DATASOURCE: Datasource = { export const PLACEHOLDER_DATASOURCE: Dataset = {
id: 0, id: 0,
type: DatasourceType.Table, type: DatasourceType.Table,
uid: '_placeholder_', uid: '_placeholder_',

View File

@ -24,7 +24,7 @@ import {
addSliceToDashboard, addSliceToDashboard,
removeSliceFromDashboard, removeSliceFromDashboard,
} from 'src/dashboard/actions/dashboardState'; } from 'src/dashboard/actions/dashboardState';
import { setDatasources } from 'src/dashboard/actions/datasources'; import { setDatasources } from 'src/datasource/actions';
import { triggerQuery } from 'src/components/Chart/chartAction'; import { triggerQuery } from 'src/components/Chart/chartAction';
import { logEvent } from 'src/logger/actions'; import { logEvent } from 'src/logger/actions';

View File

@ -36,7 +36,7 @@ import {
useDashboardDatasets, useDashboardDatasets,
} from 'src/hooks/apiResources'; } from 'src/hooks/apiResources';
import { hydrateDashboard } from 'src/dashboard/actions/hydrate'; import { hydrateDashboard } from 'src/dashboard/actions/hydrate';
import { setDatasources } from 'src/dashboard/actions/datasources'; import { setDatasources } from 'src/datasource/actions';
import injectCustomCss from 'src/dashboard/util/injectCustomCss'; import injectCustomCss from 'src/dashboard/util/injectCustomCss';
import setupPlugins from 'src/setup/setupPlugins'; import setupPlugins from 'src/setup/setupPlugins';
import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes'; import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes';

View File

@ -1,43 +0,0 @@
/**
* 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 { keyBy } from 'lodash';
import { DatasourcesState } from 'src/dashboard/types';
import {
DatasourcesActionPayload,
DatasourcesAction,
} from '../actions/datasources';
export default function datasourcesReducer(
datasources: DatasourcesState | undefined,
action: DatasourcesActionPayload,
) {
if (action.type === DatasourcesAction.SET_DATASOURCES) {
return {
...datasources,
...keyBy(action.datasources, 'uid'),
};
}
if (action.type === DatasourcesAction.SET_DATASOURCE) {
return {
...datasources,
[action.key]: action.datasource,
};
}
return datasources || {};
}

View File

@ -20,7 +20,6 @@ import {
ChartProps, ChartProps,
DataMaskStateWithId, DataMaskStateWithId,
ExtraFormData, ExtraFormData,
GenericDataType,
JsonObject, JsonObject,
NativeFiltersState, NativeFiltersState,
} from '@superset-ui/core'; } from '@superset-ui/core';
@ -84,13 +83,8 @@ export type DashboardInfo = {
export type ChartsState = { [key: string]: Chart }; export type ChartsState = { [key: string]: Chart };
export type Datasource = Dataset & {
uid: string;
column_types: GenericDataType[];
table_name: string;
};
export type DatasourcesState = { export type DatasourcesState = {
[key: string]: Datasource; [key: string]: Dataset;
}; };
/** Root state of redux */ /** Root state of redux */

View File

@ -18,39 +18,9 @@
*/ */
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import { SupersetClient } from '@superset-ui/core'; import { SupersetClient } from '@superset-ui/core';
import { Datasource, RootState } from 'src/dashboard/types'; import { Dataset } from '@superset-ui/chart-controls';
import { RootState } from 'src/dashboard/types';
// update datasources index for Dashboard import { setDatasource } from 'src/datasource/actions';
export enum DatasourcesAction {
SET_DATASOURCES = 'SET_DATASOURCES',
SET_DATASOURCE = 'SET_DATASOURCE',
}
export type DatasourcesActionPayload =
| {
type: DatasourcesAction.SET_DATASOURCES;
datasources: Datasource[] | null;
}
| {
type: DatasourcesAction.SET_DATASOURCE;
key: Datasource['uid'];
datasource: Datasource;
};
export function setDatasources(datasources: Datasource[] | null) {
return {
type: DatasourcesAction.SET_DATASOURCES,
datasources,
};
}
export function setDatasource(datasource: Datasource, key: string) {
return {
type: DatasourcesAction.SET_DATASOURCE,
key,
datasource,
};
}
export function fetchDatasourceMetadata(key: string) { export function fetchDatasourceMetadata(key: string) {
return (dispatch: Dispatch, getState: () => RootState) => { return (dispatch: Dispatch, getState: () => RootState) => {
@ -58,11 +28,11 @@ export function fetchDatasourceMetadata(key: string) {
const datasource = datasources[key]; const datasource = datasources[key];
if (datasource) { if (datasource) {
return dispatch(setDatasource(datasource, key)); return dispatch(setDatasource(datasource));
} }
return SupersetClient.get({ return SupersetClient.get({
endpoint: `/superset/fetch_datasource_metadata?datasourceKey=${key}`, endpoint: `/superset/fetch_datasource_metadata?datasourceKey=${key}`,
}).then(({ json }) => dispatch(setDatasource(json as Datasource, key))); }).then(({ json }) => dispatch(setDatasource(json as Dataset)));
}; };
} }

View File

@ -16,34 +16,39 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import { Dispatch } from 'redux';
import { Dataset } from '@superset-ui/chart-controls'; import { Dataset } from '@superset-ui/chart-controls';
import { updateFormDataByDatasource } from './exploreActions';
import { ExplorePageState } from '../types';
export const SET_DATASOURCE = 'SET_DATASOURCE'; export enum DatasourcesActionType {
export interface SetDatasource { INIT_DATASOURCES = 'INIT_DATASOURCES',
type: string; SET_DATASOURCE = 'SET_DATASOURCE',
datasource: Dataset; SET_DATASOURCES = 'SET_DATASOURCES',
} }
export type DatasourcesAction =
| {
type: DatasourcesActionType.INIT_DATASOURCES;
datasources: { [key: string]: Dataset };
}
| {
type: DatasourcesActionType.SET_DATASOURCES;
datasources: Dataset[] | null;
}
| {
type: DatasourcesActionType.SET_DATASOURCE;
datasource: Dataset;
};
export function initDatasources(datasources: { [key: string]: Dataset }) {
return { type: DatasourcesActionType.INIT_DATASOURCES, datasources };
}
export function setDatasource(datasource: Dataset) { export function setDatasource(datasource: Dataset) {
return { type: SET_DATASOURCE, datasource }; return { type: DatasourcesActionType.SET_DATASOURCE, datasource };
} }
export function changeDatasource(newDatasource: Dataset) { export function setDatasources(datasources: Dataset[] | null) {
return function (dispatch: Dispatch, getState: () => ExplorePageState) { return {
const { type: DatasourcesActionType.SET_DATASOURCES,
explore: { datasource: prevDatasource }, datasources,
} = getState();
dispatch(setDatasource(newDatasource));
dispatch(updateFormDataByDatasource(prevDatasource, newDatasource));
}; };
} }
export const datasourcesActions = {
setDatasource,
changeDatasource,
};
export type AnyDatasourcesAction = SetDatasource;

View File

@ -16,27 +16,32 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import { Dataset } from '@superset-ui/chart-controls'; import { keyBy } from 'lodash';
import { getDatasourceUid } from 'src/utils/getDatasourceUid'; import { getDatasourceUid } from 'src/utils/getDatasourceUid';
import { import {
AnyDatasourcesAction, DatasourcesAction,
SET_DATASOURCE, DatasourcesActionType,
} from '../actions/datasourcesActions'; } from 'src/datasource/actions';
import { HYDRATE_EXPLORE, HydrateExplore } from '../actions/hydrateExplore'; import { Dataset } from '@superset-ui/chart-controls';
export default function datasourcesReducer( export default function datasourcesReducer(
// TODO: change type to include other datasource types datasources: { [key: string]: Dataset } | undefined,
datasources: { [key: string]: Dataset }, action: DatasourcesAction,
action: AnyDatasourcesAction | HydrateExplore,
) { ) {
if (action.type === SET_DATASOURCE) { if (action.type === DatasourcesActionType.INIT_DATASOURCES) {
return { ...action.datasources };
}
if (action.type === DatasourcesActionType.SET_DATASOURCES) {
return {
...datasources,
...keyBy(action.datasources, 'uid'),
};
}
if (action.type === DatasourcesActionType.SET_DATASOURCE) {
return { return {
...datasources, ...datasources,
[getDatasourceUid(action.datasource)]: action.datasource, [getDatasourceUid(action.datasource)]: action.datasource,
}; };
} }
if (action.type === HYDRATE_EXPLORE) {
return { ...(action as HydrateExplore).data.datasources };
}
return datasources || {}; return datasources || {};
} }

View File

@ -1,85 +0,0 @@
/**
* 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 { DatasourceType } from '@superset-ui/core';
import {
setDatasource,
changeDatasource,
} from 'src/explore/actions/datasourcesActions';
import datasourcesReducer from '../reducers/datasourcesReducer';
import { updateFormDataByDatasource } from './exploreActions';
const CURRENT_DATASOURCE = {
id: 1,
uid: '1__table',
type: DatasourceType.Table,
columns: [],
metrics: [],
column_format: {},
verbose_map: {},
main_dttm_col: '__timestamp',
// eg. ['["ds", true]', 'ds [asc]']
datasource_name: 'test datasource',
description: null,
};
const NEW_DATASOURCE = {
id: 2,
type: DatasourceType.Table,
columns: [],
metrics: [],
column_format: {},
verbose_map: {},
main_dttm_col: '__timestamp',
// eg. ['["ds", true]', 'ds [asc]']
datasource_name: 'test datasource',
description: null,
};
const defaultDatasourcesReducerState = {
[CURRENT_DATASOURCE.uid]: CURRENT_DATASOURCE,
};
test('sets new datasource', () => {
const newState = datasourcesReducer(
defaultDatasourcesReducerState,
setDatasource(NEW_DATASOURCE),
);
expect(newState).toEqual({
...defaultDatasourcesReducerState,
'2__table': NEW_DATASOURCE,
});
});
test('change datasource action', () => {
const dispatch = jest.fn();
const getState = jest.fn(() => ({
explore: {
datasource: CURRENT_DATASOURCE,
},
}));
// ignore getState type check - we dont need explore.datasource field for this test
// @ts-ignore
changeDatasource(NEW_DATASOURCE)(dispatch, getState);
expect(dispatch).toHaveBeenCalledTimes(2);
expect(dispatch).toHaveBeenNthCalledWith(1, setDatasource(NEW_DATASOURCE));
expect(dispatch).toHaveBeenNthCalledWith(
2,
updateFormDataByDatasource(CURRENT_DATASOURCE, NEW_DATASOURCE),
);
});

View File

@ -25,6 +25,8 @@ import {
toastActions, toastActions,
} from 'src/components/MessageToasts/actions'; } from 'src/components/MessageToasts/actions';
import { Slice } from 'src/types/Chart'; import { Slice } from 'src/types/Chart';
import { setDatasource } from 'src/datasource/actions';
import { ExplorePageState } from 'src/explore/types';
const FAVESTAR_BASE_URL = '/superset/favstar/slice'; const FAVESTAR_BASE_URL = '/superset/favstar/slice';
@ -140,6 +142,16 @@ export function setForceQuery(force: boolean) {
}; };
} }
export function changeDatasource(newDatasource: Dataset) {
return function (dispatch: Dispatch, getState: () => ExplorePageState) {
const {
explore: { datasource: prevDatasource },
} = getState();
dispatch(setDatasource(newDatasource));
dispatch(updateFormDataByDatasource(prevDatasource, newDatasource));
};
}
export const exploreActions = { export const exploreActions = {
...toastActions, ...toastActions,
fetchDatasourcesStarted, fetchDatasourcesStarted,
@ -153,6 +165,7 @@ export const exploreActions = {
createNewSlice, createNewSlice,
sliceUpdated, sliceUpdated,
setForceQuery, setForceQuery,
changeDatasource,
}; };
export type ExploreActions = typeof exploreActions; export type ExploreActions = typeof exploreActions;

View File

@ -64,9 +64,6 @@ test('creates hydrate action from initial data', () => {
lastRendered: 0, lastRendered: 0,
}, },
}, },
datasources: {
'8__table': exploreInitialData.dataset,
},
saveModal: { saveModal: {
dashboards: [], dashboards: [],
saveModalAlert: null, saveModalAlert: null,

View File

@ -35,6 +35,7 @@ import { getDatasourceUid } from 'src/utils/getDatasourceUid';
import { getUrlParam } from 'src/utils/urlUtils'; import { getUrlParam } from 'src/utils/urlUtils';
import { URL_PARAMS } from 'src/constants'; import { URL_PARAMS } from 'src/constants';
import { findPermission } from 'src/utils/findPermission'; import { findPermission } from 'src/utils/findPermission';
import { initDatasources } from 'src/datasource/actions';
export const HYDRATE_EXPLORE = 'HYDRATE_EXPLORE'; export const HYDRATE_EXPLORE = 'HYDRATE_EXPLORE';
export const hydrateExplore = export const hydrateExplore =
@ -121,6 +122,13 @@ export const hydrateExplore =
lastRendered: 0, lastRendered: 0,
}; };
dispatch(
initDatasources({
...datasources,
[getDatasourceUid(initialDatasource)]: initialDatasource,
}),
);
return dispatch({ return dispatch({
type: HYDRATE_EXPLORE, type: HYDRATE_EXPLORE,
data: { data: {
@ -128,10 +136,6 @@ export const hydrateExplore =
...charts, ...charts,
[chartKey]: chart, [chartKey]: chart,
}, },
datasources: {
...datasources,
[getDatasourceUid(initialDatasource)]: initialDatasource,
},
saveModal: { saveModal: {
dashboards: [], dashboards: [],
saveModalAlert: null, saveModalAlert: null,

View File

@ -46,11 +46,10 @@ import {
import { getUrlParam } from 'src/utils/urlUtils'; import { getUrlParam } from 'src/utils/urlUtils';
import cx from 'classnames'; import cx from 'classnames';
import * as chartActions from 'src/components/Chart/chartAction'; import * as chartActions from 'src/components/Chart/chartAction';
import { fetchDatasourceMetadata } from 'src/dashboard/actions/datasources'; import { fetchDatasourceMetadata } from 'src/dashboard/util/fetchDatasourceMetadata';
import { chartPropShape } from 'src/dashboard/util/propShapes'; import { chartPropShape } from 'src/dashboard/util/propShapes';
import { mergeExtraFormData } from 'src/dashboard/components/nativeFilters/utils'; import { mergeExtraFormData } from 'src/dashboard/components/nativeFilters/utils';
import { postFormData, putFormData } from 'src/explore/exploreUtils/formData'; import { postFormData, putFormData } from 'src/explore/exploreUtils/formData';
import { datasourcesActions } from 'src/explore/actions/datasourcesActions';
import { mountExploreUrl } from 'src/explore/exploreUtils'; import { mountExploreUrl } from 'src/explore/exploreUtils';
import { getFormDataFromControls } from 'src/explore/controlUtils'; import { getFormDataFromControls } from 'src/explore/controlUtils';
import * as exploreActions from 'src/explore/actions/exploreActions'; import * as exploreActions from 'src/explore/actions/exploreActions';
@ -758,7 +757,6 @@ function mapStateToProps(state) {
function mapDispatchToProps(dispatch) { function mapDispatchToProps(dispatch) {
const actions = { const actions = {
...exploreActions, ...exploreActions,
...datasourcesActions,
...saveModalActions, ...saveModalActions,
...chartActions, ...chartActions,
...logActions, ...logActions,

View File

@ -17,7 +17,8 @@
* under the License. * under the License.
*/ */
import { Dashboard, Datasource, EmbeddedDashboard } from 'src/dashboard/types'; import { Dashboard, EmbeddedDashboard } from 'src/dashboard/types';
import { Dataset } from '@superset-ui/chart-controls';
import { Chart } from 'src/types/Chart'; import { Chart } from 'src/types/Chart';
import { useApiV1Resource, useTransformedResource } from './apiResources'; import { useApiV1Resource, useTransformedResource } from './apiResources';
@ -42,7 +43,7 @@ export const useDashboardCharts = (idOrSlug: string | number) =>
// important: this endpoint only returns the fields in the dataset // important: this endpoint only returns the fields in the dataset
// that are necessary for rendering the given dashboard // that are necessary for rendering the given dashboard
export const useDashboardDatasets = (idOrSlug: string | number) => export const useDashboardDatasets = (idOrSlug: string | number) =>
useApiV1Resource<Datasource[]>(`/api/v1/dashboard/${idOrSlug}/datasets`); useApiV1Resource<Dataset[]>(`/api/v1/dashboard/${idOrSlug}/datasets`);
export const useEmbeddedDashboard = (idOrSlug: string | number) => export const useEmbeddedDashboard = (idOrSlug: string | number) =>
useApiV1Resource<EmbeddedDashboard>(`/api/v1/dashboard/${idOrSlug}/embedded`); useApiV1Resource<EmbeddedDashboard>(`/api/v1/dashboard/${idOrSlug}/embedded`);

View File

@ -27,26 +27,17 @@ import dashboardInfo from 'src/dashboard/reducers/dashboardInfo';
import dashboardState from 'src/dashboard/reducers/dashboardState'; import dashboardState from 'src/dashboard/reducers/dashboardState';
import dashboardFilters from 'src/dashboard/reducers/dashboardFilters'; import dashboardFilters from 'src/dashboard/reducers/dashboardFilters';
import nativeFilters from 'src/dashboard/reducers/nativeFilters'; import nativeFilters from 'src/dashboard/reducers/nativeFilters';
import dashboardDatasources from 'src/dashboard/reducers/datasources'; import datasources from 'src/datasource/reducer';
import sliceEntities from 'src/dashboard/reducers/sliceEntities'; import sliceEntities from 'src/dashboard/reducers/sliceEntities';
import dashboardLayout from 'src/dashboard/reducers/undoableDashboardLayout'; import dashboardLayout from 'src/dashboard/reducers/undoableDashboardLayout';
import logger from 'src/middleware/loggerMiddleware'; import logger from 'src/middleware/loggerMiddleware';
import saveModal from 'src/explore/reducers/saveModalReducer'; import saveModal from 'src/explore/reducers/saveModalReducer';
import explore from 'src/explore/reducers/exploreReducer'; import explore from 'src/explore/reducers/exploreReducer';
import exploreDatasources from 'src/explore/reducers/datasourcesReducer';
import { DatasourcesState } from 'src/dashboard/types';
import {
DatasourcesActionPayload,
DatasourcesAction,
} from 'src/dashboard/actions/datasources';
import shortid from 'shortid'; import shortid from 'shortid';
import { import {
BootstrapUser, BootstrapUser,
UserWithPermissionsAndRoles, UserWithPermissionsAndRoles,
} from 'src/types/bootstrapTypes'; } from 'src/types/bootstrapTypes';
import { AnyDatasourcesAction } from 'src/explore/actions/datasourcesActions';
import { HydrateExplore } from 'src/explore/actions/hydrateExplore';
import { Dataset } from '@superset-ui/chart-controls';
// Some reducers don't do anything, and redux is just used to reference the initial "state". // Some reducers don't do anything, and redux is just used to reference the initial "state".
// This may change later, as the client application takes on more responsibilities. // This may change later, as the client application takes on more responsibilities.
@ -75,26 +66,6 @@ const userReducer = (
return user; return user;
}; };
// TODO: This reducer is a combination of the Dashboard and Explore reducers.
// The correct way of handling this is to unify the actions and reducers from both
// modules in shared files. This involves a big refactor to unify the parameter types
// and move files around. We should tackle this in a specific PR.
const CombinedDatasourceReducers = (
datasources: DatasourcesState | undefined | { [key: string]: Dataset },
action: DatasourcesActionPayload | AnyDatasourcesAction | HydrateExplore,
) => {
if (action.type === DatasourcesAction.SET_DATASOURCES) {
return dashboardDatasources(
datasources as DatasourcesState | undefined,
action as DatasourcesActionPayload,
);
}
return exploreDatasources(
datasources as { [key: string]: Dataset },
action as AnyDatasourcesAction | HydrateExplore,
);
};
// exported for tests // exported for tests
export const rootReducer = combineReducers({ export const rootReducer = combineReducers({
messageToasts: messageToastReducer, messageToasts: messageToastReducer,
@ -102,7 +73,7 @@ export const rootReducer = combineReducers({
user: userReducer, user: userReducer,
impressionId: noopReducer(shortid.generate()), impressionId: noopReducer(shortid.generate()),
charts, charts,
datasources: CombinedDatasourceReducers, datasources,
dashboardInfo, dashboardInfo,
dashboardFilters, dashboardFilters,
dataMask, dataMask,