diff --git a/superset/assets/src/showSavedQuery/index.jsx b/superset/assets/src/showSavedQuery/index.jsx new file mode 100644 index 00000000000..cd384fe5b46 --- /dev/null +++ b/superset/assets/src/showSavedQuery/index.jsx @@ -0,0 +1,43 @@ +/** + * 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 Form from 'react-jsonschema-form'; + +const scheduleInfoContainer = document.getElementById('schedule-info'); +const bootstrapData = JSON.parse(scheduleInfoContainer.getAttribute('data-bootstrap')); +const schemas = bootstrapData.common.feature_flags.SCHEDULED_QUERIES; +const scheduleInfo = bootstrapData.common.extra_json.schedule_info; + +if (scheduleInfo && schemas) { + // hide instructions when showing schedule info + schemas.JSONSCHEMA.description = ''; + + ReactDom.render( +
+
+
, + scheduleInfoContainer, + ); +} diff --git a/superset/assets/webpack.config.js b/superset/assets/webpack.config.js index 97a51de8130..241c5b962f1 100644 --- a/superset/assets/webpack.config.js +++ b/superset/assets/webpack.config.js @@ -119,6 +119,7 @@ const config = { sqllab: addPreamble('/src/SqlLab/index.jsx'), welcome: addPreamble('/src/welcome/index.jsx'), profile: addPreamble('/src/profile/index.jsx'), + showSavedQuery: [path.join(APP_DIR, '/src/showSavedQuery/index.jsx')], }, output, optimization: { diff --git a/superset/templates/superset/models/savedquery/show.html b/superset/templates/superset/models/savedquery/show.html new file mode 100644 index 00000000000..9ffedeedbfa --- /dev/null +++ b/superset/templates/superset/models/savedquery/show.html @@ -0,0 +1,35 @@ +{# + 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 "appbuilder/general/model/show.html" %} + +{% block show_form %} + {{ super() }} +
+{% endblock %} + +{% block tail_js %} + {{ super() }} + {% with filename="showSavedQuery" %} + {% include "superset/partials/_script_tag.html" %} + {% endwith %} +{% endblock %} diff --git a/superset/views/base.py b/superset/views/base.py index 113b9c68e39..2d14622ea89 100644 --- a/superset/views/base.py +++ b/superset/views/base.py @@ -153,7 +153,7 @@ class BaseSupersetView(BaseView): status=status, mimetype='application/json') - def common_bootsrap_payload(self): + def common_bootstrap_payload(self): """Common data always sent to the client""" messages = get_flashed_messages(with_categories=True) locale = str(get_locale()) diff --git a/superset/views/core.py b/superset/views/core.py index e79de112b8d..1f69f4049f7 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -1372,7 +1372,7 @@ class Superset(BaseSupersetView): 'standalone': standalone, 'user_id': user_id, 'forced_height': request.args.get('height'), - 'common': self.common_bootsrap_payload(), + 'common': self.common_bootstrap_payload(), } table_name = datasource.table_name \ if datasource_type == 'table' \ @@ -2231,7 +2231,7 @@ class Superset(BaseSupersetView): 'user_id': g.user.get_id(), 'dashboard_data': dashboard_data, 'datasources': {ds.uid: ds.data for ds in datasources}, - 'common': self.common_bootsrap_payload(), + 'common': self.common_bootstrap_payload(), 'editMode': edit_mode, } @@ -2919,7 +2919,7 @@ class Superset(BaseSupersetView): payload = { 'user': bootstrap_user_data(), - 'common': self.common_bootsrap_payload(), + 'common': self.common_bootstrap_payload(), } return self.render_template( @@ -2938,7 +2938,7 @@ class Superset(BaseSupersetView): payload = { 'user': bootstrap_user_data(username, include_perms=True), - 'common': self.common_bootsrap_payload(), + 'common': self.common_bootstrap_payload(), } return self.render_template( @@ -2954,7 +2954,7 @@ class Superset(BaseSupersetView): """SQL Editor""" d = { 'defaultDbId': config.get('SQLLAB_DEFAULT_DBID'), - 'common': self.common_bootsrap_payload(), + 'common': self.common_bootstrap_payload(), } return self.render_template( 'superset/basic.html', diff --git a/superset/views/sql_lab.py b/superset/views/sql_lab.py index b9d1f2eb350..37c84c27052 100644 --- a/superset/views/sql_lab.py +++ b/superset/views/sql_lab.py @@ -20,13 +20,15 @@ from typing import Callable from flask import g, redirect from flask_appbuilder import expose from flask_appbuilder.models.sqla.interface import SQLAInterface -from flask_appbuilder.security.decorators import has_access +from flask_appbuilder.security.decorators import has_access, has_access_api from flask_babel import gettext as __ from flask_babel import lazy_gettext as _ from flask_sqlalchemy import BaseQuery +import simplejson as json -from superset import appbuilder, security_manager +from superset import appbuilder, get_feature_flags, security_manager from superset.models.sql_lab import Query, SavedQuery +from superset.utils import core as utils from .base import BaseSupersetView, DeleteMixin, SupersetFilter, SupersetModelView @@ -107,12 +109,36 @@ class SavedQueryView(SupersetModelView, DeleteMixin): 'changed_on': _('Changed on'), } + show_template = 'superset/models/savedquery/show.html' + def pre_add(self, obj): obj.user = g.user def pre_update(self, obj): self.pre_add(obj) + @has_access + @expose('show/') + def show(self, pk): + pk = self._deserialize_pk_if_composite(pk) + widgets = self._show(pk) + extra_json = self.datamodel.get(pk).extra_json + payload = { + 'common': { + 'feature_flags': get_feature_flags(), + 'extra_json': json.loads(extra_json), + }, + } + + return self.render_template( + self.show_template, + pk=pk, + title=self.show_title, + widgets=widgets, + related_views=self._related_views, + bootstrap_data=json.dumps(payload, default=utils.json_iso_dttm_ser), + ) + class SavedQueryViewApi(SavedQueryView): list_columns = [ @@ -123,6 +149,11 @@ class SavedQueryViewApi(SavedQueryView): add_columns = show_columns edit_columns = add_columns + @has_access_api + @expose('show/') + def show(self, pk): + return super().show(pk) + appbuilder.add_view_no_menu(SavedQueryViewApi) appbuilder.add_view_no_menu(SavedQueryView)