mirror of
https://github.com/apache/superset.git
synced 2024-09-06 13:57:40 -04:00
feat: Reuse Dashboard redux data in Explore (#20668)
This commit is contained in:
parent
c795dc23b9
commit
ff5b4bc0e4
@ -17,6 +17,6 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default function isDefined(x: unknown) {
|
export default function isDefined<T>(x: T): x is NonNullable<T> {
|
||||||
return x !== null && x !== undefined;
|
return x !== null && x !== undefined;
|
||||||
}
|
}
|
||||||
|
@ -150,9 +150,13 @@ export const hydrateDashboard =
|
|||||||
datasource: slice.form_data.datasource,
|
datasource: slice.form_data.datasource,
|
||||||
description: slice.description,
|
description: slice.description,
|
||||||
description_markeddown: slice.description_markeddown,
|
description_markeddown: slice.description_markeddown,
|
||||||
owners: slice.owners,
|
owners: slice.owners.map(owner => owner.id),
|
||||||
modified: slice.modified,
|
modified: slice.modified,
|
||||||
changed_on: new Date(slice.changed_on).getTime(),
|
changed_on: new Date(slice.changed_on).getTime(),
|
||||||
|
is_managed_externally: slice.is_managed_externally,
|
||||||
|
query_context: slice.query_context,
|
||||||
|
certified_by: slice.certified_by,
|
||||||
|
certification_details: slice.certification_details,
|
||||||
};
|
};
|
||||||
|
|
||||||
sliceIds.add(key);
|
sliceIds.add(key);
|
||||||
|
@ -302,7 +302,7 @@ class Chart extends React.Component {
|
|||||||
) {
|
) {
|
||||||
window.open(url, '_blank', 'noreferrer');
|
window.open(url, '_blank', 'noreferrer');
|
||||||
} else {
|
} else {
|
||||||
this.props.history.push(url);
|
this.props.history.push(url, { dashboardId: this.props.dashboardId });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logging.error(error);
|
logging.error(error);
|
||||||
|
@ -16,10 +16,13 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { makeApi, t } from '@superset-ui/core';
|
import { isDefined, makeApi, SupersetClient, t } from '@superset-ui/core';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
import Loading from 'src/components/Loading';
|
import Loading from 'src/components/Loading';
|
||||||
|
import pick from 'lodash/pick';
|
||||||
|
import { Dataset } from '@superset-ui/chart-controls';
|
||||||
import { getParsedExploreURLParams } from './exploreUtils/getParsedExploreURLParams';
|
import { getParsedExploreURLParams } from './exploreUtils/getParsedExploreURLParams';
|
||||||
import { hydrateExplore } from './actions/hydrateExplore';
|
import { hydrateExplore } from './actions/hydrateExplore';
|
||||||
import ExploreViewContainer from './components/ExploreViewContainer';
|
import ExploreViewContainer from './components/ExploreViewContainer';
|
||||||
@ -27,6 +30,10 @@ import { ExploreResponsePayload } from './types';
|
|||||||
import { fallbackExploreInitialData } from './fixtures';
|
import { fallbackExploreInitialData } from './fixtures';
|
||||||
import { addDangerToast } from '../components/MessageToasts/actions';
|
import { addDangerToast } from '../components/MessageToasts/actions';
|
||||||
import { isNullish } from '../utils/common';
|
import { isNullish } from '../utils/common';
|
||||||
|
import { getUrlParam } from '../utils/urlUtils';
|
||||||
|
import { URL_PARAMS } from '../constants';
|
||||||
|
import { RootState } from '../dashboard/types';
|
||||||
|
import { Slice } from '../types/Chart';
|
||||||
|
|
||||||
const loadErrorMessage = t('Failed to load chart data.');
|
const loadErrorMessage = t('Failed to load chart data.');
|
||||||
|
|
||||||
@ -38,12 +45,58 @@ const fetchExploreData = () => {
|
|||||||
})(exploreUrlParams);
|
})(exploreUrlParams);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const useExploreInitialData = (
|
||||||
|
shouldUseDashboardData: boolean,
|
||||||
|
sliceId: string | null,
|
||||||
|
) => {
|
||||||
|
const slice = useSelector<RootState, Slice | null>(({ sliceEntities }) =>
|
||||||
|
isDefined(sliceId) ? sliceEntities?.slices?.[sliceId] : null,
|
||||||
|
);
|
||||||
|
const formData = slice?.form_data;
|
||||||
|
const { id: datasourceId, type: datasourceType } = useSelector<
|
||||||
|
RootState,
|
||||||
|
{ id: number | undefined; type: string | undefined }
|
||||||
|
>(({ datasources }) =>
|
||||||
|
formData?.datasource
|
||||||
|
? pick(datasources[formData.datasource], ['id', 'type'])
|
||||||
|
: { id: undefined, type: undefined },
|
||||||
|
);
|
||||||
|
return useCallback(() => {
|
||||||
|
if (
|
||||||
|
!shouldUseDashboardData ||
|
||||||
|
!isDefined(slice) ||
|
||||||
|
!isDefined(formData) ||
|
||||||
|
!isDefined(datasourceId) ||
|
||||||
|
!isDefined(datasourceType)
|
||||||
|
) {
|
||||||
|
return fetchExploreData();
|
||||||
|
}
|
||||||
|
return SupersetClient.get({
|
||||||
|
endpoint: `/datasource/get/${datasourceType}/${datasourceId}/`,
|
||||||
|
}).then(({ json }) => ({
|
||||||
|
result: {
|
||||||
|
slice,
|
||||||
|
form_data: formData,
|
||||||
|
dataset: json as Dataset,
|
||||||
|
message: '',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
||||||
const ExplorePage = () => {
|
const ExplorePage = () => {
|
||||||
const [isLoaded, setIsLoaded] = useState(false);
|
const [isLoaded, setIsLoaded] = useState(false);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const location = useLocation<{ dashboardId?: number }>();
|
||||||
|
|
||||||
|
const getExploreInitialData = useExploreInitialData(
|
||||||
|
isDefined(location.state?.dashboardId),
|
||||||
|
getUrlParam(URL_PARAMS.sliceId),
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchExploreData()
|
getExploreInitialData()
|
||||||
.then(({ result }) => {
|
.then(({ result }) => {
|
||||||
if (isNullish(result.dataset?.id) && isNullish(result.dataset?.uid)) {
|
if (isNullish(result.dataset?.id) && isNullish(result.dataset?.uid)) {
|
||||||
dispatch(hydrateExplore(fallbackExploreInitialData));
|
dispatch(hydrateExplore(fallbackExploreInitialData));
|
||||||
|
@ -56,7 +56,7 @@ export const hydrateExplore =
|
|||||||
initialFormData.dashboardId = dashboardId;
|
initialFormData.dashboardId = dashboardId;
|
||||||
}
|
}
|
||||||
const initialDatasource =
|
const initialDatasource =
|
||||||
datasources?.[initialFormData.datasource] ?? dataset;
|
dataset ?? datasources?.[initialFormData.datasource];
|
||||||
|
|
||||||
const initialExploreState = {
|
const initialExploreState = {
|
||||||
form_data: initialFormData,
|
form_data: initialFormData,
|
||||||
|
@ -121,6 +121,7 @@ description_markeddown_description = "Sanitized HTML version of the chart descri
|
|||||||
owners_name_description = "Name of an owner of the chart."
|
owners_name_description = "Name of an owner of the chart."
|
||||||
certified_by_description = "Person or group that has certified this chart"
|
certified_by_description = "Person or group that has certified this chart"
|
||||||
certification_details_description = "Details of the certification"
|
certification_details_description = "Details of the certification"
|
||||||
|
is_managed_externally_description = "If the chart is managed outside externally"
|
||||||
|
|
||||||
#
|
#
|
||||||
# OpenAPI method specification overrides
|
# OpenAPI method specification overrides
|
||||||
@ -148,6 +149,10 @@ openapi_spec_methods_override = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UserSchema(Schema):
|
||||||
|
id = fields.Int()
|
||||||
|
|
||||||
|
|
||||||
class ChartEntityResponseSchema(Schema):
|
class ChartEntityResponseSchema(Schema):
|
||||||
"""
|
"""
|
||||||
Schema for a chart object
|
Schema for a chart object
|
||||||
@ -165,6 +170,11 @@ class ChartEntityResponseSchema(Schema):
|
|||||||
slice_url = fields.String(description=slice_url_description)
|
slice_url = fields.String(description=slice_url_description)
|
||||||
certified_by = fields.String(description=certified_by_description)
|
certified_by = fields.String(description=certified_by_description)
|
||||||
certification_details = fields.String(description=certification_details_description)
|
certification_details = fields.String(description=certification_details_description)
|
||||||
|
is_managed_externally = fields.Boolean(
|
||||||
|
description=is_managed_externally_description
|
||||||
|
)
|
||||||
|
owners = fields.List(fields.Nested(UserSchema))
|
||||||
|
query_context = fields.String(description=query_context_description)
|
||||||
|
|
||||||
|
|
||||||
class ChartPostSchema(Schema):
|
class ChartPostSchema(Schema):
|
||||||
|
Loading…
Reference in New Issue
Block a user