superset-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From maximebeauche...@apache.org
Subject [incubator-superset] branch master updated: Add universal "New" button (#6670)
Date Thu, 17 Jan 2019 23:48:46 GMT
This is an automated email from the ASF dual-hosted git repository.

maximebeauchemin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 6718588  Add universal "New" button (#6670)
6718588 is described below

commit 67185887812fc41f516567dce95358a9ba2f5c34
Author: Maxime Beauchemin <maximebeauchemin@gmail.com>
AuthorDate: Thu Jan 17 15:48:40 2019 -0800

    Add universal "New" button (#6670)
    
    * [cosmetic] CRUD's list from 'Add Filter' to 'Filter Results'
    
    * Add global new button
    
    * A better viz type selector
    
    * lint
    
    * Move view to new module, add unit test
    
    * 'Filter Results' -> 'Filter'
    
    * db merge
    
    * Filter -> 'Filter List'
---
 .../addSlice/AddSliceContainer_spec.jsx            |  7 +++-
 superset/assets/src/addSlice/AddSliceContainer.jsx | 20 +++-------
 superset/migrations/versions/8b70aa3d0f87_.py      | 22 +++++++++++
 .../appbuilder/general/widgets/search.html         |  2 +-
 superset/templates/appbuilder/navbar_right.html    | 15 +++++++-
 superset/views/__init__.py                         |  1 +
 superset/views/dashboard.py                        | 43 ++++++++++++++++++++++
 tests/dashboard_tests.py                           | 10 +++++
 8 files changed, 101 insertions(+), 19 deletions(-)

diff --git a/superset/assets/spec/javascripts/addSlice/AddSliceContainer_spec.jsx b/superset/assets/spec/javascripts/addSlice/AddSliceContainer_spec.jsx
index c842c04..e16b988 100644
--- a/superset/assets/spec/javascripts/addSlice/AddSliceContainer_spec.jsx
+++ b/superset/assets/spec/javascripts/addSlice/AddSliceContainer_spec.jsx
@@ -20,7 +20,9 @@ import React from 'react';
 import { shallow } from 'enzyme';
 import { Button } from 'react-bootstrap';
 import Select from 'react-virtualized-select';
+
 import AddSliceContainer from '../../../src/addSlice/AddSliceContainer';
+import VizTypeControl from '../../../src/explore/components/controls/VizTypeControl';
 
 const defaultProps = {
   datasources: [
@@ -40,8 +42,9 @@ describe('AddSliceContainer', () => {
     expect(wrapper.state().visType).toBe('table');
   });
 
-  it('renders 2 selects', () => {
-    expect(wrapper.find(Select)).toHaveLength(2);
+  it('renders a select and a VizTypeControl', () => {
+    expect(wrapper.find(Select)).toHaveLength(1);
+    expect(wrapper.find(VizTypeControl)).toHaveLength(1);
   });
 
   it('renders a button', () => {
diff --git a/superset/assets/src/addSlice/AddSliceContainer.jsx b/superset/assets/src/addSlice/AddSliceContainer.jsx
index bb3166c..6935690 100644
--- a/superset/assets/src/addSlice/AddSliceContainer.jsx
+++ b/superset/assets/src/addSlice/AddSliceContainer.jsx
@@ -21,7 +21,8 @@ import PropTypes from 'prop-types';
 import { Button, Panel } from 'react-bootstrap';
 import Select from 'react-virtualized-select';
 import { t } from '@superset-ui/translation';
-import { getChartMetadataRegistry } from '@superset-ui/chart';
+
+import VizTypeControl from '../explore/components/controls/VizTypeControl';
 
 const propTypes = {
   datasources: PropTypes.arrayOf(PropTypes.shape({
@@ -65,8 +66,8 @@ export default class AddSliceContainer extends React.PureComponent {
     });
   }
 
-  changeVisType(e) {
-    this.setState({ visType: e.value });
+  changeVisType(visType) {
+    this.setState({ visType });
   }
 
   isBtnDisabled() {
@@ -74,12 +75,6 @@ export default class AddSliceContainer extends React.PureComponent {
   }
 
   render() {
-    const types = getChartMetadataRegistry().entries()
-      .map(({ key, value }) => ({
-        value: key,
-        label: value.name,
-      }));
-
     return (
       <div className="container">
         <Panel header={<h3>{t('Create a new chart')}</h3>}>
@@ -108,17 +103,14 @@ export default class AddSliceContainer extends React.PureComponent {
           <br />
           <div>
             <p>{t('Choose a visualization type')}</p>
-            <Select
-              clearable={false}
+            <VizTypeControl
               name="select-vis-type"
-              style={styleSelectWidth}
               onChange={this.changeVisType}
-              options={types}
-              placeholder={t('Choose a visualization type')}
               value={this.state.visType}
             />
           </div>
           <br />
+          <hr />
           <Button
             bsStyle="primary"
             disabled={this.isBtnDisabled()}
diff --git a/superset/migrations/versions/8b70aa3d0f87_.py b/superset/migrations/versions/8b70aa3d0f87_.py
new file mode 100644
index 0000000..9368e60
--- /dev/null
+++ b/superset/migrations/versions/8b70aa3d0f87_.py
@@ -0,0 +1,22 @@
+"""empty message
+
+Revision ID: 8b70aa3d0f87
+Revises: ('fbd55e0f83eb', 'fb13d49b72f9')
+Create Date: 2019-01-17 08:31:55.781032
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '8b70aa3d0f87'
+down_revision = ('fbd55e0f83eb', 'fb13d49b72f9')
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    pass
+
+
+def downgrade():
+    pass
diff --git a/superset/templates/appbuilder/general/widgets/search.html b/superset/templates/appbuilder/general/widgets/search.html
index 688936f..eb703dc 100644
--- a/superset/templates/appbuilder/general/widgets/search.html
+++ b/superset/templates/appbuilder/general/widgets/search.html
@@ -3,7 +3,7 @@
 <div class="list-search-container">
     <form id="filter_form" class="form-search" method="get">
         <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
-        <i class="fa fa-filter text-primary" aria-hidden="true"></i> {{_("Add
Filter")}}
+        <i class="fa fa-filter text-primary" aria-hidden="true"></i> {{_("Filter
List")}}
         </button>
 
         <ul class="dropdown-menu">
diff --git a/superset/templates/appbuilder/navbar_right.html b/superset/templates/appbuilder/navbar_right.html
index 1d6fb69..bc188ef 100644
--- a/superset/templates/appbuilder/navbar_right.html
+++ b/superset/templates/appbuilder/navbar_right.html
@@ -3,6 +3,19 @@
 {% if not locale %}
     {% set locale = 'en' %}
 {% endif %}
+
+{% if not current_user.is_anonymous %}
+    <li class="dropdown">
+        <button type="button" style="margin-top: 12px; margin-right: 30px;" data-toggle="dropdown"
class="dropdown-toggle btn btn-sm btn-primary">
+          <i class="fa fa-plus"></i> {{ _("New") }}
+        </button>
+        <ul class="dropdown-menu">
+            <li><a href="/superset/sqllab"><span class="fa fa-fw fa-search"></span>
{{_("SQL Query")}}</a></li>
+            <li><a href="/chart/add"><span class="fa fa-fw fa-bar-chart"></span>
{{_("Chart")}}</a></li>
+            <li><a href="/dashboard/new/"><span class="fa fa-fw fa-dashboard"></span>
{{_("Dashboard")}}</a></li>
+        </ul>
+    </li>
+{% endif %}
 {% if languages.keys()|length > 1 %}
 <li class="dropdown">
     <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0)">
@@ -25,8 +38,6 @@
 </li>
 {% endif %}
 
-
-
 {% if not current_user.is_anonymous %}
     <li class="dropdown">
       <a
diff --git a/superset/views/__init__.py b/superset/views/__init__.py
index 8b51016..386e16e 100644
--- a/superset/views/__init__.py
+++ b/superset/views/__init__.py
@@ -18,6 +18,7 @@ from . import base  # noqa
 from . import api # noqa
 from . import core  # noqa
 from . import sql_lab  # noqa
+from . import dashboard # noqa
 from . import annotations # noqa
 from . import datasource # noqa
 from . import schedules # noqa
diff --git a/superset/views/dashboard.py b/superset/views/dashboard.py
new file mode 100644
index 0000000..f4b992d
--- /dev/null
+++ b/superset/views/dashboard.py
@@ -0,0 +1,43 @@
+# pylint: disable=C,R,W
+# 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.
+from flask import g, redirect
+from flask_appbuilder import expose
+from flask_appbuilder.security.decorators import has_access
+
+from superset import appbuilder, db
+from superset.models import core as models
+from .base import BaseSupersetView
+
+
+class Dashboard(BaseSupersetView):
+    """The base views for Superset!"""
+
+    @has_access
+    @expose('/new/')
+    def new(self):
+        """Creates a new, blank dashboard and redirects to it in edit mode"""
+        new_dashboard = models.Dashboard(
+            dashboard_title='[ untitled dashboard ]',
+            owners=[g.user],
+        )
+        db.session.add(new_dashboard)
+        db.session.commit()
+        return redirect(f'/superset/dashboard/{new_dashboard.id}/?edit=true')
+
+
+appbuilder.add_view_no_menu(Dashboard)
diff --git a/tests/dashboard_tests.py b/tests/dashboard_tests.py
index 2d6fe1a..bf3e7d1 100644
--- a/tests/dashboard_tests.py
+++ b/tests/dashboard_tests.py
@@ -19,6 +19,7 @@ import json
 import unittest
 
 from flask import escape
+from sqlalchemy import func
 
 from superset import db, security_manager
 from superset.connectors.sqla.models import SqlaTable
@@ -68,6 +69,15 @@ class DashboardTests(SupersetTestCase):
         for title, url in urls.items():
             assert escape(title) in self.client.get(url).data.decode('utf-8')
 
+    def test_new_dashboard(self):
+        self.login(username='admin')
+        dash_count_before = db.session.query(func.count(models.Dashboard.id)).first()[0]
+        url = '/dashboard/new/'
+        resp = self.get_resp(url)
+        self.assertIn('[ untitled dashboard ]', resp)
+        dash_count_after = db.session.query(func.count(models.Dashboard.id)).first()[0]
+        self.assertEquals(dash_count_before + 1, dash_count_after)
+
     def test_dashboard_modes(self):
         self.login(username='admin')
         dash = (


Mime
View raw message