From 5623cd64ca49c307df2cb5dc56d8981f7f68f081 Mon Sep 17 00:00:00 2001 From: Moriah Kreeger Date: Wed, 16 Sep 2020 21:08:40 -0700 Subject: [PATCH] feat: update saved query backend routing + add savedquery list (#10922) * Update saved query backend routing + add savedquery list * add spec fileg * add FE flag for SIP_34_SAVED_QUERIES_UI --- .../data/savedquery/SavedQueryList_spec.jsx | 45 ++++++++++++++++++ superset-frontend/src/featureFlags.ts | 1 + superset-frontend/src/views/App.tsx | 10 +++- .../src/views/CRUD/data/common.ts | 5 +- .../CRUD/data/savedquery/SavedQueryList.tsx | 46 +++++++++++++++++++ superset/views/sql_lab.py | 14 +++++- 6 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 superset-frontend/spec/javascripts/views/CRUD/data/savedquery/SavedQueryList_spec.jsx create mode 100644 superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx diff --git a/superset-frontend/spec/javascripts/views/CRUD/data/savedquery/SavedQueryList_spec.jsx b/superset-frontend/spec/javascripts/views/CRUD/data/savedquery/SavedQueryList_spec.jsx new file mode 100644 index 00000000000..cba919e6c59 --- /dev/null +++ b/superset-frontend/spec/javascripts/views/CRUD/data/savedquery/SavedQueryList_spec.jsx @@ -0,0 +1,45 @@ +/** + * 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 thunk from 'redux-thunk'; +import configureStore from 'redux-mock-store'; +import { styledMount as mount } from 'spec/helpers/theming'; +import SavedQueryList from 'src/views/CRUD/data/savedquery/SavedQueryList'; +import SubMenu from 'src/components/Menu/SubMenu'; +import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; + +// store needed for withToasts(DatabaseList) +const mockStore = configureStore([thunk]); +const store = mockStore({}); + +describe('SavedQueryList', () => { + const wrapper = mount(, { context: { store } }); + + beforeAll(async () => { + await waitForComponentToPaint(wrapper); + }); + + it('renders', () => { + expect(wrapper.find(SavedQueryList)).toExist(); + }); + + it('renders a SubMenu', () => { + expect(wrapper.find(SubMenu)).toExist(); + }); +}); diff --git a/superset-frontend/src/featureFlags.ts b/superset-frontend/src/featureFlags.ts index c8cdc26fa2a..db6434aa1d1 100644 --- a/superset-frontend/src/featureFlags.ts +++ b/superset-frontend/src/featureFlags.ts @@ -27,6 +27,7 @@ export enum FeatureFlag { SHARE_QUERIES_VIA_KV_STORE = 'SHARE_QUERIES_VIA_KV_STORE', SQLLAB_BACKEND_PERSISTENCE = 'SQLLAB_BACKEND_PERSISTENCE', THUMBNAILS = 'THUMBNAILS', + SIP_34_SAVED_QUERIES_UI = 'SIP_34_SAVED_QUERIES_UI', } export type FeatureFlagMap = { diff --git a/superset-frontend/src/views/App.tsx b/superset-frontend/src/views/App.tsx index 10604beef98..eff98835785 100644 --- a/superset-frontend/src/views/App.tsx +++ b/superset-frontend/src/views/App.tsx @@ -31,7 +31,8 @@ import FlashProvider from 'src/components/FlashProvider'; import DashboardList from 'src/views/CRUD/dashboard/DashboardList'; import ChartList from 'src/views/CRUD/chart/ChartList'; import DatasetList from 'src/views/CRUD/data/dataset/DatasetList'; -import DatasourceList from 'src/views/CRUD/data/database/DatabaseList'; +import DatabaseList from 'src/views/CRUD/data/database/DatabaseList'; +import SavedQueryList from 'src/views/CRUD/data/savedquery/SavedQueryList'; import messageToastReducer from '../messageToasts/reducers'; import { initEnhancer } from '../reduxUtils'; @@ -88,7 +89,12 @@ const App = () => ( - + + + + + + diff --git a/superset-frontend/src/views/CRUD/data/common.ts b/superset-frontend/src/views/CRUD/data/common.ts index 6cd6b393ef8..0400a427a3c 100644 --- a/superset-frontend/src/views/CRUD/data/common.ts +++ b/superset-frontend/src/views/CRUD/data/common.ts @@ -17,6 +17,7 @@ * under the License. */ import { t } from '@superset-ui/core'; +import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags'; export const commonMenuData = { name: t('Data'), @@ -36,8 +37,8 @@ export const commonMenuData = { { name: 'Saved Queries', label: t('Saved Queries'), - url: '/sqllab/my_queries/', - usesRouter: false, + url: '/savedqueryview/list/', + usesRouter: isFeatureEnabled(FeatureFlag.SIP_34_SAVED_QUERIES_UI), }, ], }; diff --git a/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx b/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx new file mode 100644 index 00000000000..4b55ee4c2e7 --- /dev/null +++ b/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx @@ -0,0 +1,46 @@ +/** + * 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 withToasts from 'src/messageToasts/enhancers/withToasts'; +import SubMenu, { SubMenuProps } from 'src/components/Menu/SubMenu'; +import { commonMenuData } from 'src/views/CRUD/data/common'; + +interface SavedQueryListProps { + addDangerToast: (msg: string) => void; + addSuccessToast: (msg: string) => void; +} + +function SavedQueryList({ + addDangerToast, + addSuccessToast, +}: SavedQueryListProps) { + const menuData: SubMenuProps = { + activeChild: 'Saved Queries', + ...commonMenuData, + }; + + return ( + <> + + + ); +} + +export default withToasts(SavedQueryList); diff --git a/superset/views/sql_lab.py b/superset/views/sql_lab.py index a85fb534124..63df0ae0cb6 100644 --- a/superset/views/sql_lab.py +++ b/superset/views/sql_lab.py @@ -21,8 +21,9 @@ from flask_appbuilder.models.sqla.interface import SQLAInterface from flask_appbuilder.security.decorators import has_access, has_access_api from flask_babel import lazy_gettext as _ -from superset import db +from superset import app, db from superset.constants import RouteMethod +from superset.extensions import feature_flag_manager from superset.models.sql_lab import Query, SavedQuery, TableSchema, TabState from superset.typing import FlaskResponse from superset.utils import core as utils @@ -75,6 +76,17 @@ class SavedQueryView( "changed_on": _("Changed on"), } + @expose("/list/") + @has_access + def list(self) -> FlaskResponse: + if not ( + app.config["ENABLE_REACT_CRUD_VIEWS"] + and feature_flag_manager.is_feature_enabled("SIP_34_SAVED_QUERIES_UI") + ): + return super().list() + + return super().render_app_template() + def pre_add(self, item: "SavedQueryView") -> None: item.user = g.user