From ec2eb3ddf883505fb9681a5783602181a1aea747 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Wed, 13 Jul 2022 08:50:58 -0300 Subject: [PATCH] refactor: Renders addSlice in SPA (#20675) * refactor: Renders addSlice in SPA * Removes unused imports * Fixes test imports * Removes unnecessary imports --- .../src/addSlice/AddSliceContainer.test.tsx | 22 ++++--- .../src/addSlice/AddSliceContainer.tsx | 9 +-- superset-frontend/src/addSlice/App.tsx | 66 ------------------- superset-frontend/src/addSlice/index.tsx | 23 ------- .../src/views/CRUD/chart/ChartList.tsx | 6 +- .../src/views/components/RightMenu.tsx | 24 +++++-- superset-frontend/src/views/routes.tsx | 10 +++ superset-frontend/webpack.config.js | 1 - superset/templates/superset/add_slice.html | 35 ---------- superset/views/chart/views.py | 14 +--- 10 files changed, 52 insertions(+), 158 deletions(-) delete mode 100644 superset-frontend/src/addSlice/App.tsx delete mode 100644 superset-frontend/src/addSlice/index.tsx delete mode 100644 superset/templates/superset/add_slice.html diff --git a/superset-frontend/src/addSlice/AddSliceContainer.test.tsx b/superset-frontend/src/addSlice/AddSliceContainer.test.tsx index b26ac9a4a76ac..e5f62fd258eb5 100644 --- a/superset-frontend/src/addSlice/AddSliceContainer.test.tsx +++ b/superset-frontend/src/addSlice/AddSliceContainer.test.tsx @@ -17,7 +17,8 @@ * under the License. */ import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; +import { ReactWrapper } from 'enzyme'; +import { styledMount as mount } from 'spec/helpers/theming'; import Button from 'src/components/Button'; import { AsyncSelect } from 'src/components'; import { @@ -28,8 +29,6 @@ import { import VizTypeGallery from 'src/explore/components/controls/VizTypeControl/VizTypeGallery'; import { act } from 'spec/helpers/testing-library'; import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes'; -import { ThemeProvider } from '@emotion/react'; -import { supersetTheme } from '@superset-ui/core'; const datasource = { value: '1', @@ -62,13 +61,20 @@ const mockUserWithDatasetWrite: UserWithPermissionsAndRoles = { isAnonymous: false, }; +// We don't need the actual implementation for the tests +const routeProps = { + history: {} as any, + location: {} as any, + match: {} as any, +}; + async function getWrapper(user = mockUser) { const wrapper = mount( - null} />, - { - wrappingComponent: ThemeProvider, - wrappingComponentProps: { theme: supersetTheme }, - }, + null} + {...routeProps} + />, ) as unknown as ReactWrapper< AddSliceContainerProps, AddSliceContainerState, diff --git a/superset-frontend/src/addSlice/AddSliceContainer.tsx b/superset-frontend/src/addSlice/AddSliceContainer.tsx index 98821c71a1b67..9507327776868 100644 --- a/superset-frontend/src/addSlice/AddSliceContainer.tsx +++ b/superset-frontend/src/addSlice/AddSliceContainer.tsx @@ -23,6 +23,7 @@ import { styled, t, SupersetClient, JsonResponse } from '@superset-ui/core'; import { getUrlParam } from 'src/utils/urlUtils'; import { URL_PARAMS } from 'src/constants'; import { isNullish } from 'src/utils/common'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; import Button from 'src/components/Button'; import { AsyncSelect, Steps } from 'src/components'; import { Tooltip } from 'src/components/Tooltip'; @@ -42,10 +43,10 @@ type Dataset = { datasource_type: string; }; -export type AddSliceContainerProps = { +export interface AddSliceContainerProps extends RouteComponentProps { user: UserWithPermissionsAndRoles; addSuccessToast: (arg: string) => void; -}; +} export type AddSliceContainerState = { datasource?: { label: string; value: string }; @@ -254,7 +255,7 @@ export class AddSliceContainer extends React.PureComponent< } gotoSlice() { - window.location.href = this.exploreUrl(); + this.props.history.push(this.exploreUrl()); } changeDatasource(datasource: { label: string; value: string }) { @@ -418,4 +419,4 @@ export class AddSliceContainer extends React.PureComponent< } } -export default withToasts(AddSliceContainer); +export default withRouter(withToasts(AddSliceContainer)); diff --git a/superset-frontend/src/addSlice/App.tsx b/superset-frontend/src/addSlice/App.tsx deleted file mode 100644 index 11adbb30a2d07..0000000000000 --- a/superset-frontend/src/addSlice/App.tsx +++ /dev/null @@ -1,66 +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 React from 'react'; -import { hot } from 'react-hot-loader/root'; -import thunk from 'redux-thunk'; -import { createStore, compose, applyMiddleware, combineReducers } from 'redux'; -import { Provider } from 'react-redux'; -import { ThemeProvider } from '@superset-ui/core'; -import { GlobalStyles } from 'src/GlobalStyles'; -import messageToastReducer from 'src/components/MessageToasts/reducers'; -import { initEnhancer } from 'src/reduxUtils'; -import ToastContainer from 'src/components/MessageToasts/ToastContainer'; -import setupApp from '../setup/setupApp'; -import setupPlugins from '../setup/setupPlugins'; -import { DynamicPluginProvider } from '../components/DynamicPlugins'; -import AddSliceContainer from './AddSliceContainer'; -import { initFeatureFlags } from '../featureFlags'; -import { theme } from '../preamble'; - -setupApp(); -setupPlugins(); - -const addSliceContainer = document.getElementById('app'); -const bootstrapData = JSON.parse( - addSliceContainer?.getAttribute('data-bootstrap') || '{}', -); - -const store = createStore( - combineReducers({ - messageToasts: messageToastReducer, - }), - {}, - compose(applyMiddleware(thunk), initEnhancer(false)), -); - -initFeatureFlags(bootstrapData.common.feature_flags); - -const App = () => ( - - - - - - - - - -); - -export default hot(App); diff --git a/superset-frontend/src/addSlice/index.tsx b/superset-frontend/src/addSlice/index.tsx deleted file mode 100644 index c257009e64fd5..0000000000000 --- a/superset-frontend/src/addSlice/index.tsx +++ /dev/null @@ -1,23 +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 React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; - -ReactDOM.render(, document.getElementById('app')); diff --git a/superset-frontend/src/views/CRUD/chart/ChartList.tsx b/superset-frontend/src/views/CRUD/chart/ChartList.tsx index c2ffcf028483f..8173b73c0663a 100644 --- a/superset-frontend/src/views/CRUD/chart/ChartList.tsx +++ b/superset-frontend/src/views/CRUD/chart/ChartList.tsx @@ -41,7 +41,7 @@ import handleResourceExport from 'src/utils/export'; import ConfirmStatusChange from 'src/components/ConfirmStatusChange'; import SubMenu, { SubMenuProps } from 'src/views/components/SubMenu'; import FaveStar from 'src/components/FaveStar'; -import { Link } from 'react-router-dom'; +import { Link, useHistory } from 'react-router-dom'; import ListView, { Filter, FilterOperator, @@ -153,6 +153,8 @@ function ChartList(props: ChartListProps) { user: { userId }, } = props; + const history = useHistory(); + const { state: { loading, @@ -653,7 +655,7 @@ function ChartList(props: ChartListProps) { ), buttonStyle: 'primary', onClick: () => { - window.location.assign('/chart/add'); + history.push('/chart/add'); }, }); diff --git a/superset-frontend/src/views/components/RightMenu.tsx b/superset-frontend/src/views/components/RightMenu.tsx index e1e2dd1ae70f1..5473fa069c288 100644 --- a/superset-frontend/src/views/components/RightMenu.tsx +++ b/superset-frontend/src/views/components/RightMenu.tsx @@ -321,13 +321,23 @@ const RightMenu = ({ roles, ) && ( - - {' '} - {menu.label} - + {isFrontendRoute(menu.url) ? ( + + {' '} + {menu.label} + + ) : ( + + {' '} + {menu.label} + + )} ) ); diff --git a/superset-frontend/src/views/routes.tsx b/superset-frontend/src/views/routes.tsx index e0d9d144bff9b..dbb9ca2fab858 100644 --- a/superset-frontend/src/views/routes.tsx +++ b/superset-frontend/src/views/routes.tsx @@ -21,6 +21,12 @@ import React, { lazy } from 'react'; // not lazy loaded since this is the home page. import Welcome from 'src/views/CRUD/welcome/Welcome'; +const AddSliceContainer = lazy( + () => + import( + /* webpackChunkName: "AddSliceContainer" */ 'src/addSlice/AddSliceContainer' + ), +); const AnnotationLayersList = lazy( () => import( @@ -117,6 +123,10 @@ export const routes: Routes = [ path: '/superset/dashboard/:idOrSlug/', Component: DashboardRoute, }, + { + path: '/chart/add', + Component: AddSliceContainer, + }, { path: '/chart/list/', Component: ChartList, diff --git a/superset-frontend/webpack.config.js b/superset-frontend/webpack.config.js index 450453a946c55..99d51a7d01901 100644 --- a/superset-frontend/webpack.config.js +++ b/superset-frontend/webpack.config.js @@ -209,7 +209,6 @@ const config = { menu: addPreamble('src/views/menu.tsx'), spa: addPreamble('/src/views/index.tsx'), embedded: addPreamble('/src/embedded/index.tsx'), - addSlice: addPreamble('/src/addSlice/index.tsx'), sqllab: addPreamble('/src/SqlLab/index.tsx'), profile: addPreamble('/src/profile/index.tsx'), showSavedQuery: [path.join(APP_DIR, '/src/showSavedQuery/index.jsx')], diff --git a/superset/templates/superset/add_slice.html b/superset/templates/superset/add_slice.html deleted file mode 100644 index b287de64e869d..0000000000000 --- a/superset/templates/superset/add_slice.html +++ /dev/null @@ -1,35 +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. -#} -{% extends "superset/basic.html" %} - -{% block title %} - Add new chart -{% endblock %} - -{% block body %} -
-{% endblock %} - -{% block tail_js %} - {{ super() }} - {{ js_bundle("addSlice") }} -{% endblock %} diff --git a/superset/views/chart/views.py b/superset/views/chart/views.py index 4d43e797d09c3..250fa901e9a6d 100644 --- a/superset/views/chart/views.py +++ b/superset/views/chart/views.py @@ -14,9 +14,6 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import json - -from flask import g from flask_appbuilder import expose, has_access from flask_appbuilder.models.sqla.interface import SQLAInterface from flask_babel import lazy_gettext as _ @@ -26,9 +23,8 @@ from superset.models.slice import Slice from superset.superset_typing import FlaskResponse from superset.utils import core as utils -from superset.views.base import common_bootstrap_payload, DeleteMixin, SupersetModelView +from superset.views.base import DeleteMixin, SupersetModelView from superset.views.chart.mixin import SliceMixin -from superset.views.utils import bootstrap_user_data class SliceModelView( @@ -57,13 +53,7 @@ def pre_delete(self, item: "SliceModelView") -> None: @expose("/add", methods=["GET", "POST"]) @has_access def add(self) -> FlaskResponse: - payload = { - "common": common_bootstrap_payload(), - "user": bootstrap_user_data(g.user, include_perms=True), - } - return self.render_template( - "superset/add_slice.html", bootstrap_data=json.dumps(payload) - ) + return super().render_app_template() @expose("/list/") @has_access