You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ch...@apache.org on 2019/03/25 22:19:48 UTC

[incubator-superset] branch master updated: SQL editor layout makeover (#7102)

This is an automated email from the ASF dual-hosted git repository.

christine 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 71f1bbd  SQL editor layout makeover (#7102)
71f1bbd is described below

commit 71f1bbd2ec59b99d6ba6d9a4a2f9cfceaf922b80
Author: Christine Chambers <ch...@gmail.com>
AuthorDate: Mon Mar 25 15:19:43 2019 -0700

    SQL editor layout makeover (#7102)
    
    This PR includes the following layout and css tweaks:
    - Using flex to layout the north and south sub panes of query pane so resizing works properly in both Chrome and Firefox
    - Removal of necessary wrapper divs and tweaking of css in sql lab so we can scroll to the bottom of both the table list and the results pane
    - Make sql lab's content not overflow vertically and layout the query result area to eliminate double scroll bars
    - css tweaks on the basic.html page so the loading animation appears in the center of the page across the board
---
 superset/assets/cypress/integration/sqllab/tabs.js |   2 +-
 superset/assets/package-lock.json                  | 221 ++++++++++-----------
 superset/assets/src/SqlLab/components/App.jsx      |  16 +-
 .../assets/src/SqlLab/components/ResultSet.jsx     |   4 +-
 .../assets/src/SqlLab/components/SouthPane.jsx     |  13 +-
 .../assets/src/SqlLab/components/SqlEditor.jsx     |  72 ++++---
 .../src/SqlLab/components/SqlEditorLeftBar.jsx     |  16 +-
 .../src/SqlLab/components/TabbedSqlEditors.jsx     | 108 +++++-----
 superset/assets/src/SqlLab/main.less               | 154 ++++++++------
 .../components/FilterableTable/FilterableTable.jsx |  19 +-
 .../FilterableTable/FilterableTableStyles.css      |   3 -
 superset/assets/src/components/TableSelector.css   |   2 +-
 .../src/dashboard/stylesheets/dashboard.less       |  12 +-
 .../assets/stylesheets/less/cosmo/bootswatch.less  |  36 ++--
 superset/assets/stylesheets/less/index.less        |  19 ++
 superset/assets/stylesheets/superset.less          |  15 +-
 superset/templates/superset/basic.html             |   4 +-
 17 files changed, 376 insertions(+), 340 deletions(-)

diff --git a/superset/assets/cypress/integration/sqllab/tabs.js b/superset/assets/cypress/integration/sqllab/tabs.js
index 17026ce..0d9731e 100644
--- a/superset/assets/cypress/integration/sqllab/tabs.js
+++ b/superset/assets/cypress/integration/sqllab/tabs.js
@@ -42,7 +42,7 @@ export default () => {
         const initialTabCount = tabListA.length;
 
         // open the tab dropdown to remove
-        cy.get('#a11y-query-editor-tabs > ul > li:first button').click();
+        cy.get('#a11y-query-editor-tabs > ul > li:first button:nth-child(2)').click();
 
         // first item is close
         cy.get('#a11y-query-editor-tabs > ul > li:first ul li a')
diff --git a/superset/assets/package-lock.json b/superset/assets/package-lock.json
index a0e8dce..81fcbaa 100644
--- a/superset/assets/package-lock.json
+++ b/superset/assets/package-lock.json
@@ -1368,7 +1368,7 @@
     },
     "@data-ui/event-flow": {
       "version": "0.0.54",
-      "resolved": "https://registry.npmjs.org/@data-ui/event-flow/-/event-flow-0.0.54.tgz",
+      "resolved": "http://registry.npmjs.org/@data-ui/event-flow/-/event-flow-0.0.54.tgz",
       "integrity": "sha1-uwPh/StWNCSGVbjfnTxsOKdH5l4=",
       "requires": {
         "@data-ui/forms": "0.0.50",
@@ -1659,7 +1659,7 @@
     },
     "@data-ui/radial-chart": {
       "version": "0.0.54",
-      "resolved": "https://registry.npmjs.org/@data-ui/radial-chart/-/radial-chart-0.0.54.tgz",
+      "resolved": "http://registry.npmjs.org/@data-ui/radial-chart/-/radial-chart-0.0.54.tgz",
       "integrity": "sha1-DSiwdoHZtgJ9msI7cpJBgn1RMAE=",
       "requires": {
         "@data-ui/shared": "0.0.54",
@@ -1674,7 +1674,7 @@
     },
     "@data-ui/shared": {
       "version": "0.0.54",
-      "resolved": "https://registry.npmjs.org/@data-ui/shared/-/shared-0.0.54.tgz",
+      "resolved": "http://registry.npmjs.org/@data-ui/shared/-/shared-0.0.54.tgz",
       "integrity": "sha1-L7DW3ukNrCC/jzwpE8aFCoIj1Zs=",
       "requires": {
         "@data-ui/theme": "0.0.48",
@@ -1747,7 +1747,7 @@
     },
     "@data-ui/sparkline": {
       "version": "0.0.54",
-      "resolved": "https://registry.npmjs.org/@data-ui/sparkline/-/sparkline-0.0.54.tgz",
+      "resolved": "http://registry.npmjs.org/@data-ui/sparkline/-/sparkline-0.0.54.tgz",
       "integrity": "sha1-zj0WbZ4LI5oLoC84lMuejIQXHO8=",
       "requires": {
         "@data-ui/shared": "0.0.54",
@@ -2201,7 +2201,7 @@
     },
     "@sinonjs/formatio": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz",
+      "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz",
       "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==",
       "dev": true,
       "requires": {
@@ -2252,7 +2252,7 @@
       "dependencies": {
         "whatwg-fetch": {
           "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
+          "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
           "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
         }
       }
@@ -3308,7 +3308,7 @@
     },
     "acorn-jsx": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
       "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
       "dev": true,
       "requires": {
@@ -3317,7 +3317,7 @@
       "dependencies": {
         "acorn": {
           "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+          "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
           "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
           "dev": true
         }
@@ -3752,7 +3752,7 @@
     },
     "array-equal": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
+      "resolved": "http://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
       "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
       "dev": true
     },
@@ -3875,7 +3875,7 @@
         },
         "util": {
           "version": "0.10.3",
-          "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+          "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz",
           "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
           "dev": true,
           "requires": {
@@ -4365,7 +4365,7 @@
     },
     "babel-plugin-syntax-dynamic-import": {
       "version": "6.18.0",
-      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
       "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=",
       "dev": true
     },
@@ -4649,7 +4649,7 @@
     },
     "brace": {
       "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz",
+      "resolved": "http://registry.npmjs.org/brace/-/brace-0.11.1.tgz",
       "integrity": "sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg="
     },
     "brace-expansion": {
@@ -4681,7 +4681,7 @@
     },
     "brfs": {
       "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz",
+      "resolved": "http://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz",
       "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==",
       "requires": {
         "quote-stream": "^1.0.1",
@@ -4713,7 +4713,7 @@
       "dependencies": {
         "resolve": {
           "version": "1.1.7",
-          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+          "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
           "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
           "dev": true
         }
@@ -4721,7 +4721,7 @@
     },
     "browserify-aes": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
       "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
       "dev": true,
       "requires": {
@@ -4758,7 +4758,7 @@
     },
     "browserify-rsa": {
       "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
       "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
       "dev": true,
       "requires": {
@@ -4810,7 +4810,7 @@
     },
     "buffer": {
       "version": "4.9.1",
-      "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+      "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
       "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
       "dev": true,
       "requires": {
@@ -4943,7 +4943,7 @@
       "dependencies": {
         "callsites": {
           "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+          "resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
           "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
           "dev": true
         }
@@ -4960,7 +4960,7 @@
     },
     "callsites": {
       "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
       "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
       "dev": true
     },
@@ -5262,7 +5262,7 @@
     },
     "clean-webpack-plugin": {
       "version": "0.1.19",
-      "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-0.1.19.tgz",
+      "resolved": "http://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-0.1.19.tgz",
       "integrity": "sha512-M1Li5yLHECcN2MahoreuODul5LkjohJGFxLPTjl3j1ttKrF5rgjZET1SJduuqxLAuT1gAPOdkhg03qcaaU1KeA==",
       "dev": true,
       "requires": {
@@ -5673,7 +5673,7 @@
     },
     "create-hash": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
       "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
       "dev": true,
       "requires": {
@@ -5686,7 +5686,7 @@
     },
     "create-hmac": {
       "version": "1.1.7",
-      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+      "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
       "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
       "dev": true,
       "requires": {
@@ -5747,7 +5747,7 @@
     },
     "css-color-names": {
       "version": "0.0.4",
-      "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
+      "resolved": "http://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
       "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
       "dev": true
     },
@@ -5811,7 +5811,7 @@
     },
     "css-in-js-utils": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
       "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
       "requires": {
         "hyphenate-style-name": "^1.0.2",
@@ -5871,7 +5871,7 @@
     },
     "css-select": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
       "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
       "dev": true,
       "requires": {
@@ -6259,7 +6259,7 @@
     },
     "d3-geo-projection": {
       "version": "0.2.16",
-      "resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-0.2.16.tgz",
+      "resolved": "http://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-0.2.16.tgz",
       "integrity": "sha1-SZTs0QM92xUztsTFUoocgdzClCc=",
       "requires": {
         "brfs": "^1.3.0"
@@ -6677,7 +6677,7 @@
     },
     "diffie-hellman": {
       "version": "5.0.3",
-      "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
       "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
       "dev": true,
       "requires": {
@@ -6707,7 +6707,7 @@
     },
     "dnd-core": {
       "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-2.6.0.tgz",
+      "resolved": "http://registry.npmjs.org/dnd-core/-/dnd-core-2.6.0.tgz",
       "integrity": "sha1-ErrWbVh0LG5ffPKUP7aFlED4CcQ=",
       "requires": {
         "asap": "^2.0.6",
@@ -6837,7 +6837,7 @@
     },
     "duplexer": {
       "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+      "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
       "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
       "dev": true
     },
@@ -7079,7 +7079,7 @@
     },
     "es6-promise": {
       "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
+      "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
       "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM="
     },
     "es6bindall": {
@@ -7126,7 +7126,7 @@
     },
     "eslint": {
       "version": "4.19.1",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
+      "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
       "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
       "dev": true,
       "requires": {
@@ -7230,7 +7230,7 @@
         },
         "fast-deep-equal": {
           "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+          "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
           "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
           "dev": true
         },
@@ -7404,7 +7404,7 @@
       "dependencies": {
         "doctrine": {
           "version": "1.5.0",
-          "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+          "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
           "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
           "dev": true,
           "requires": {
@@ -7414,7 +7414,7 @@
         },
         "load-json-file": {
           "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+          "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
           "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
           "dev": true,
           "requires": {
@@ -7552,7 +7552,7 @@
     },
     "espree": {
       "version": "3.5.4",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
+      "resolved": "http://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
       "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
       "dev": true,
       "requires": {
@@ -7732,7 +7732,7 @@
       "dependencies": {
         "source-map": {
           "version": "0.5.0",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.0.tgz",
+          "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.5.0.tgz",
           "integrity": "sha1-D+llA6yGpa213mP05BKuSHLNvoY=",
           "dev": true
         }
@@ -7778,7 +7778,7 @@
       "dependencies": {
         "array-flatten": {
           "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+          "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
           "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
           "dev": true
         },
@@ -7806,7 +7806,7 @@
     },
     "external-editor": {
       "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
       "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
       "dev": true,
       "requires": {
@@ -8028,7 +8028,7 @@
     },
     "file-loader": {
       "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
+      "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
       "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
       "dev": true,
       "requires": {
@@ -8038,7 +8038,7 @@
     },
     "file-type": {
       "version": "3.9.0",
-      "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
+      "resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
       "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
     },
     "fileset": {
@@ -8071,7 +8071,7 @@
     },
     "finalhandler": {
       "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+      "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
       "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
       "dev": true,
       "requires": {
@@ -8684,8 +8684,7 @@
         "ansi-regex": {
           "version": "2.1.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -8706,14 +8705,12 @@
         "balanced-match": {
           "version": "1.0.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -8728,20 +8725,17 @@
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "concat-map": {
           "version": "0.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -8858,8 +8852,7 @@
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "ini": {
           "version": "1.3.5",
@@ -8871,7 +8864,6 @@
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -8886,7 +8878,6 @@
           "version": "3.0.4",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -8894,14 +8885,12 @@
         "minimist": {
           "version": "0.0.8",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "minipass": {
           "version": "2.2.4",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.1",
             "yallist": "^3.0.0"
@@ -8920,7 +8909,6 @@
           "version": "0.5.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -9001,8 +8989,7 @@
         "number-is-nan": {
           "version": "1.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -9014,7 +9001,6 @@
           "version": "1.4.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -9100,8 +9086,7 @@
         "safe-buffer": {
           "version": "5.1.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -9137,7 +9122,6 @@
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -9157,7 +9141,6 @@
           "version": "3.0.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -9201,14 +9184,12 @@
         "wrappy": {
           "version": "1.0.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "yallist": {
           "version": "3.0.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         }
       }
     },
@@ -9317,7 +9298,7 @@
     },
     "gettext-parser": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/gettext-parser/-/gettext-parser-1.1.0.tgz",
       "integrity": "sha1-LFpmONiTk0ubVQN9CtgstwBLJnk=",
       "dev": true,
       "requires": {
@@ -9409,7 +9390,7 @@
     },
     "globby": {
       "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
       "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
       "dev": true,
       "requires": {
@@ -9498,7 +9479,7 @@
         },
         "minimist": {
           "version": "0.0.10",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
           "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
           "dev": true
         },
@@ -9686,7 +9667,7 @@
     },
     "hoist-non-react-statics": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz",
       "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs="
     },
     "homedir-polyfill": {
@@ -9790,7 +9771,7 @@
     },
     "http-errors": {
       "version": "1.6.3",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+      "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
       "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
       "dev": true,
       "requires": {
@@ -10538,7 +10519,7 @@
     },
     "is-accessor-descriptor": {
       "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
       "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
       "dev": true,
       "requires": {
@@ -10626,7 +10607,7 @@
     },
     "is-data-descriptor": {
       "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
       "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
       "dev": true,
       "requires": {
@@ -10731,7 +10712,7 @@
     },
     "is-obj": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
       "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
       "dev": true
     },
@@ -12604,7 +12585,7 @@
     },
     "magic-string": {
       "version": "0.22.5",
-      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz",
+      "resolved": "http://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz",
       "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==",
       "requires": {
         "vlq": "^0.2.2"
@@ -12727,7 +12708,7 @@
         },
         "minimist": {
           "version": "0.0.8",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
           "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
         },
         "quickselect": {
@@ -12785,7 +12766,7 @@
     },
     "mathjs": {
       "version": "3.20.2",
-      "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-3.20.2.tgz",
+      "resolved": "http://registry.npmjs.org/mathjs/-/mathjs-3.20.2.tgz",
       "integrity": "sha512-3f6/+uf1cUtIz1rYFz775wekl/UEDSQ3mU6xdxW7qzpvvhc2v28i3UtLsGTRB+u8OqDWoSX6Dz8gehaGFs6tCA==",
       "requires": {
         "complex.js": "2.0.4",
@@ -12835,7 +12816,7 @@
     },
     "media-typer": {
       "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
       "dev": true
     },
@@ -13035,7 +13016,7 @@
     },
     "minimist": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
       "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
     },
     "mississippi": {
@@ -13087,7 +13068,7 @@
     },
     "mkdirp": {
       "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "requires": {
         "minimist": "0.0.8"
@@ -13095,7 +13076,7 @@
       "dependencies": {
         "minimist": {
           "version": "0.0.8",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
           "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
         }
       }
@@ -13762,7 +13743,7 @@
     },
     "os-tmpdir": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
       "dev": true
     },
@@ -13949,7 +13930,7 @@
     },
     "path-browserify": {
       "version": "0.0.0",
-      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+      "resolved": "http://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
       "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
       "dev": true
     },
@@ -13967,7 +13948,7 @@
     },
     "path-is-absolute": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
     },
     "path-is-inside": {
@@ -14108,7 +14089,7 @@
     },
     "po2json": {
       "version": "0.4.5",
-      "resolved": "https://registry.npmjs.org/po2json/-/po2json-0.4.5.tgz",
+      "resolved": "http://registry.npmjs.org/po2json/-/po2json-0.4.5.tgz",
       "integrity": "sha1-R7spUtoy1Yob4vJWpZjuvAt0URg=",
       "dev": true,
       "requires": {
@@ -14170,7 +14151,7 @@
       "dependencies": {
         "async": {
           "version": "1.5.2",
-          "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+          "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
           "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
           "dev": true
         }
@@ -16338,7 +16319,7 @@
     },
     "react-ace": {
       "version": "5.10.0",
-      "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-5.10.0.tgz",
+      "resolved": "http://registry.npmjs.org/react-ace/-/react-ace-5.10.0.tgz",
       "integrity": "sha512-aEK/XZCowP8IXq91e2DYqOtGhabk1bbjt+fyeW0UBcIkzDzP/RX/MeJKeyW7wsZcwElACVwyy9nnwXBTqgky3A==",
       "requires": {
         "brace": "^0.11.0",
@@ -16417,7 +16398,7 @@
     },
     "react-dnd": {
       "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-2.6.0.tgz",
+      "resolved": "http://registry.npmjs.org/react-dnd/-/react-dnd-2.6.0.tgz",
       "integrity": "sha1-f6JWds+CfViokSk+PBq1naACVFo=",
       "requires": {
         "disposables": "^1.0.1",
@@ -16437,7 +16418,7 @@
     },
     "react-dnd-html5-backend": {
       "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-2.6.0.tgz",
+      "resolved": "http://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-2.6.0.tgz",
       "integrity": "sha1-WQzRzKeEQbsnTt1XH+9MCxbdz44=",
       "requires": {
         "lodash": "^4.2.0"
@@ -16564,7 +16545,7 @@
         },
         "minimist": {
           "version": "0.0.8",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
           "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
         },
         "mjolnir.js": {
@@ -16885,7 +16866,7 @@
     },
     "readable-stream": {
       "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+      "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
       "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
       "requires": {
         "core-util-is": "~1.0.0",
@@ -17236,7 +17217,7 @@
     },
     "reduce-css-calc": {
       "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
+      "resolved": "http://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
       "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=",
       "requires": {
         "balanced-match": "^0.4.2",
@@ -17359,7 +17340,7 @@
     },
     "regexpp": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
       "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
       "dev": true
     },
@@ -17391,7 +17372,7 @@
       "dependencies": {
         "jsesc": {
           "version": "0.5.0",
-          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+          "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
           "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
           "dev": true
         }
@@ -17507,7 +17488,7 @@
     },
     "require-uncached": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
       "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
       "dev": true,
       "requires": {
@@ -17590,7 +17571,7 @@
     },
     "rgba-regex": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz",
+      "resolved": "http://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz",
       "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=",
       "dev": true
     },
@@ -17674,7 +17655,7 @@
     },
     "safe-regex": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
       "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
       "dev": true,
       "requires": {
@@ -17852,7 +17833,7 @@
     },
     "sha.js": {
       "version": "2.4.11",
-      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+      "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
       "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
       "dev": true,
       "requires": {
@@ -17887,7 +17868,7 @@
         },
         "iconv-lite": {
           "version": "0.2.11",
-          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz",
+          "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz",
           "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg="
         }
       }
@@ -17907,7 +17888,7 @@
       "dependencies": {
         "minimist": {
           "version": "0.0.5",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
           "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY="
         }
       }
@@ -17966,7 +17947,7 @@
     },
     "sinon": {
       "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz",
+      "resolved": "http://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz",
       "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==",
       "dev": true,
       "requires": {
@@ -18358,7 +18339,7 @@
     },
     "split": {
       "version": "0.2.10",
-      "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz",
+      "resolved": "http://registry.npmjs.org/split/-/split-0.2.10.tgz",
       "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=",
       "requires": {
         "through": "2"
@@ -18401,7 +18382,7 @@
     },
     "sprintf-js": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
       "dev": true
     },
@@ -18563,7 +18544,7 @@
         },
         "readable-stream": {
           "version": "1.1.14",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
           "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
           "requires": {
             "core-util-is": "~1.0.0",
@@ -18574,7 +18555,7 @@
         },
         "string_decoder": {
           "version": "0.10.31",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
           "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
         }
       }
@@ -18653,7 +18634,7 @@
     },
     "string_decoder": {
       "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
       "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
       "requires": {
         "safe-buffer": "~5.1.0"
@@ -18661,7 +18642,7 @@
     },
     "strip-ansi": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
       "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
       "dev": true,
       "requires": {
@@ -18676,7 +18657,7 @@
     },
     "strip-eof": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+      "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
       "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
       "dev": true
     },
@@ -18921,7 +18902,7 @@
         },
         "fast-deep-equal": {
           "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+          "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
           "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
           "dev": true
         },
@@ -18978,7 +18959,7 @@
     },
     "tapable": {
       "version": "0.1.10",
-      "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz",
+      "resolved": "http://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz",
       "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=",
       "dev": true
     },
@@ -19166,7 +19147,7 @@
     },
     "through": {
       "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
     },
     "through2": {
@@ -19862,7 +19843,7 @@
     },
     "tty-browserify": {
       "version": "0.0.0",
-      "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+      "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
       "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
       "dev": true
     },
@@ -20395,7 +20376,7 @@
     },
     "vm-browserify": {
       "version": "0.0.4",
-      "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+      "resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
       "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
       "dev": true,
       "requires": {
@@ -21977,7 +21958,7 @@
     },
     "wrap-ansi": {
       "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
       "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
       "dev": true,
       "requires": {
@@ -22062,7 +22043,7 @@
     },
     "xmlbuilder": {
       "version": "9.0.7",
-      "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+      "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
       "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
     },
     "xregexp": {
diff --git a/superset/assets/src/SqlLab/components/App.jsx b/superset/assets/src/SqlLab/components/App.jsx
index 25c61de..e4e516a 100644
--- a/superset/assets/src/SqlLab/components/App.jsx
+++ b/superset/assets/src/SqlLab/components/App.jsx
@@ -71,26 +71,18 @@ class App extends React.PureComponent {
   render() {
     let content;
     if (this.state.hash) {
-      content = (
-        <div className="container-fluid">
-          <div className="row">
-            <div className="col-md-12">
-              <QuerySearch height={this.state.contentHeight} actions={this.props.actions} />
-            </div>
-          </div>
-        </div>
-      );
+      content = <QuerySearch height={this.state.contentHeight} actions={this.props.actions} />;
     } else {
       content = (
-        <div>
+        <React.Fragment>
           <QueryAutoRefresh />
           <TabbedSqlEditors />
-        </div>
+        </React.Fragment>
       );
     }
     return (
       <div className="App SqlLab">
-        <div className="container-fluid">{content}</div>
+        {content}
         <ToastPresenter />
       </div>
     );
diff --git a/superset/assets/src/SqlLab/components/ResultSet.jsx b/superset/assets/src/SqlLab/components/ResultSet.jsx
index 7c3ea19..12dfca7 100644
--- a/superset/assets/src/SqlLab/components/ResultSet.jsx
+++ b/superset/assets/src/SqlLab/components/ResultSet.jsx
@@ -207,7 +207,7 @@ export default class ResultSet extends React.PureComponent {
       }
       if (data && data.length > 0) {
         return (
-          <div>
+          <React.Fragment>
             {this.renderControls.bind(this)()}
             {sql}
             <FilterableTable
@@ -216,7 +216,7 @@ export default class ResultSet extends React.PureComponent {
               height={height}
               filterText={this.state.searchText}
             />
-          </div>
+          </React.Fragment>
         );
       } else if (data && data.length === 0) {
         return <Alert bsStyle="warning">The query returned no data</Alert>;
diff --git a/superset/assets/src/SqlLab/components/SouthPane.jsx b/superset/assets/src/SqlLab/components/SouthPane.jsx
index 441104c..c3dd57b 100644
--- a/superset/assets/src/SqlLab/components/SouthPane.jsx
+++ b/superset/assets/src/SqlLab/components/SouthPane.jsx
@@ -29,6 +29,8 @@ import QueryHistory from './QueryHistory';
 import ResultSet from './ResultSet';
 import { STATUS_OPTIONS, STATE_BSSTYLE_MAP } from '../constants';
 
+const TAB_HEIGHT = 44;
+
 /*
     editorQueries are queries executed by users passed from SqlEditor component
     dataPrebiewQueries are all queries executed for preview of table data (from SqlEditorLeft)
@@ -76,7 +78,7 @@ export class SouthPane extends React.PureComponent {
           { STATUS_OPTIONS.offline }
         </Label>);
     }
-    const innerTabHeight = this.state.height - 55;
+    const innerTabContentHeight = this.state.height - TAB_HEIGHT;
     let latestQuery;
     const props = this.props;
     if (props.editorQueries.length > 0) {
@@ -90,7 +92,7 @@ export class SouthPane extends React.PureComponent {
           search
           query={latestQuery}
           actions={props.actions}
-          height={innerTabHeight}
+          height={innerTabContentHeight}
           database={this.props.databases[latestQuery.dbId]}
         />
       );
@@ -109,7 +111,7 @@ export class SouthPane extends React.PureComponent {
           csv={false}
           actions={props.actions}
           cache
-          height={innerTabHeight}
+          height={innerTabContentHeight}
         />
       </Tab>
     ));
@@ -119,6 +121,7 @@ export class SouthPane extends React.PureComponent {
         <Tabs
           bsStyle="tabs"
           animation={false}
+          className="SouthPaneTabs"
           id={shortid.generate()}
           activeKey={this.props.activeSouthPaneTab}
           onSelect={this.switchTab}
@@ -133,9 +136,7 @@ export class SouthPane extends React.PureComponent {
             title={t('Query History')}
             eventKey="History"
           >
-            <div style={{ height: `${innerTabHeight}px`, overflow: 'auto' }}>
-              <QueryHistory queries={props.editorQueries} actions={props.actions} />
-            </div>
+            <QueryHistory queries={props.editorQueries} actions={props.actions} />
           </Tab>
           {dataPreviewTabs}
         </Tabs>
diff --git a/superset/assets/src/SqlLab/components/SqlEditor.jsx b/superset/assets/src/SqlLab/components/SqlEditor.jsx
index cf142b2..fdb7d45 100644
--- a/superset/assets/src/SqlLab/components/SqlEditor.jsx
+++ b/superset/assets/src/SqlLab/components/SqlEditor.jsx
@@ -44,8 +44,10 @@ import AceEditorWrapper from './AceEditorWrapper';
 import { STATE_BSSTYLE_MAP } from '../constants';
 import RunQueryActionButton from './RunQueryActionButton';
 
+const SQL_EDITOR_PADDING = 10;
 const SQL_TOOLBAR_HEIGHT = 51;
 const GUTTER_HEIGHT = 5;
+const GUTTER_MARGIN = 3;
 const INITIAL_NORTH_PERCENT = 30;
 const INITIAL_SOUTH_PERCENT = 70;
 
@@ -81,6 +83,7 @@ class SqlEditor extends React.PureComponent {
     this.sqlEditorRef = React.createRef();
     this.northPaneRef = React.createRef();
 
+    this.elementStyle = this.elementStyle.bind(this);
     this.onResizeStart = this.onResizeStart.bind(this);
     this.onResizeEnd = this.onResizeEnd.bind(this);
     this.runQuery = this.runQuery.bind(this);
@@ -124,14 +127,16 @@ class SqlEditor extends React.PureComponent {
   }
   // One layer of abstraction for easy spying in unit tests
   getSqlEditorHeight() {
-    return this.sqlEditorRef.current ? this.sqlEditorRef.current.clientHeight : 0;
+    return this.sqlEditorRef.current ?
+      (this.sqlEditorRef.current.clientHeight - SQL_EDITOR_PADDING * 2) : 0;
   }
   // Return the heights for the ace editor and the south pane as an object
   // given the height of the sql editor, north pane percent and south pane percent.
   getAceEditorAndSouthPaneHeights(height, northPercent, southPercent) {
     return {
-      aceEditorHeight: height * northPercent / 100 - SQL_TOOLBAR_HEIGHT - GUTTER_HEIGHT / 2,
-      southPaneHeight: height * southPercent / 100,
+      aceEditorHeight: height * northPercent / 100 - (GUTTER_HEIGHT / 2 + GUTTER_MARGIN)
+        - SQL_TOOLBAR_HEIGHT,
+      southPaneHeight: height * southPercent / 100 - (GUTTER_HEIGHT / 2 + GUTTER_MARGIN),
     };
   }
   getHotkeyConfig() {
@@ -174,6 +179,11 @@ class SqlEditor extends React.PureComponent {
   setQueryLimit(queryLimit) {
     this.props.actions.queryEditorSetQueryLimit(this.props.queryEditor, queryLimit);
   }
+  elementStyle(dimension, elementSize, gutterSize) {
+    return {
+      [dimension]: `calc(${elementSize}% - ${gutterSize + GUTTER_MARGIN}px)`,
+    };
+  }
   runQuery() {
     if (this.props.database) {
       this.startQuery(this.props.database.allow_run_async);
@@ -212,36 +222,36 @@ class SqlEditor extends React.PureComponent {
     const { aceEditorHeight, southPaneHeight } = this.getAceEditorAndSouthPaneHeights(
       this.state.height, INITIAL_NORTH_PERCENT, INITIAL_SOUTH_PERCENT);
     return (
-      <div className="queryPane">
-        <Split
-          sizes={[INITIAL_NORTH_PERCENT, INITIAL_SOUTH_PERCENT]}
-          minSize={200}
-          direction="vertical"
-          gutterSize={GUTTER_HEIGHT}
-          onDragStart={this.onResizeStart}
-          onDragEnd={this.onResizeEnd}
-        >
-          <div ref={this.northPaneRef}>
-            <AceEditorWrapper
-              actions={this.props.actions}
-              onBlur={this.setQueryEditorSql}
-              onChange={this.onSqlChanged}
-              queryEditor={this.props.queryEditor}
-              sql={this.props.queryEditor.sql}
-              tables={this.props.tables}
-              height={`${this.state.aceEditorHeight || aceEditorHeight}px`}
-              hotkeys={hotkeys}
-            />
-            {this.renderEditorBottomBar(hotkeys)}
-          </div>
-          <SouthPane
-            editorQueries={this.props.editorQueries}
-            dataPreviewQueries={this.props.dataPreviewQueries}
+      <Split
+        className="queryPane"
+        sizes={[INITIAL_NORTH_PERCENT, INITIAL_SOUTH_PERCENT]}
+        elementStyle={this.elementStyle}
+        minSize={200}
+        direction="vertical"
+        gutterSize={GUTTER_HEIGHT}
+        onDragStart={this.onResizeStart}
+        onDragEnd={this.onResizeEnd}
+      >
+        <div ref={this.northPaneRef}>
+          <AceEditorWrapper
             actions={this.props.actions}
-            height={this.state.southPaneHeight || southPaneHeight}
+            onBlur={this.setQueryEditorSql}
+            onChange={this.onSqlChanged}
+            queryEditor={this.props.queryEditor}
+            sql={this.props.queryEditor.sql}
+            tables={this.props.tables}
+            height={`${this.state.aceEditorHeight || aceEditorHeight}px`}
+            hotkeys={hotkeys}
           />
-        </Split>
-      </div>
+          {this.renderEditorBottomBar(hotkeys)}
+        </div>
+        <SouthPane
+          editorQueries={this.props.editorQueries}
+          dataPreviewQueries={this.props.dataPreviewQueries}
+          actions={this.props.actions}
+          height={this.state.southPaneHeight || southPaneHeight}
+        />
+      </Split>
     );
   }
   renderEditorBottomBar(hotkeys) {
diff --git a/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx b/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
index 0de18b0..9d0796c 100644
--- a/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
+++ b/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
@@ -105,7 +105,7 @@ export default class SqlEditorLeftBar extends React.PureComponent {
     const tableMetaDataHeight = this.props.height - 130; // 130 is the height of the selects above
     const qe = this.props.queryEditor;
     return (
-      <div className="sqlEditorLeftBar">
+      <div className="SqlEditorLeftBar">
         <TableSelector
           dbId={qe.dbId}
           schema={qe.schema}
@@ -117,14 +117,12 @@ export default class SqlEditorLeftBar extends React.PureComponent {
           database={this.props.database}
           handleError={this.props.actions.addDangerToast}
         />
-        <hr />
-        <div className="m-t-5">
-          <div className="scrollbar-container">
-            <div className="scrollbar-content" style={{ height: tableMetaDataHeight }}>
-              {this.props.tables.map(table => (
-                <TableElement table={table} key={table.id} actions={this.props.actions} />
-              ))}
-            </div>
+        <div className="divider" />
+        <div className="scrollbar-container">
+          <div className="scrollbar-content" style={{ height: tableMetaDataHeight }}>
+            {this.props.tables.map(table => (
+              <TableElement table={table} key={table.id} actions={this.props.actions} />
+            ))}
           </div>
         </div>
         {shouldShowReset &&
diff --git a/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx b/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
index c287b70..a8516f1 100644
--- a/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
+++ b/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
@@ -18,7 +18,7 @@
  */
 import React from 'react';
 import PropTypes from 'prop-types';
-import { DropdownButton, MenuItem, Tab, Tabs } from 'react-bootstrap';
+import { MenuItem, SplitButton, Tab, Tabs } from 'react-bootstrap';
 import { connect } from 'react-redux';
 import { bindActionCreators } from 'redux';
 import URI from 'urijs';
@@ -196,64 +196,62 @@ class TabbedSqlEditors extends React.PureComponent {
       }
       const state = latestQuery ? latestQuery.state : '';
 
-      const tabTitle = (
-        <div>
+      const title = (
+        <React.Fragment>
           <TabStatusIcon onClose={() => this.removeQueryEditor(qe)} tabState={state} />{' '}
           {qe.title}{' '}
-          <DropdownButton
-            bsSize="small"
-            id={'ddbtn-tab-' + i}
-            className="ddbtn-tab"
-            title=""
-          >
-            <MenuItem eventKey="1" onClick={() => this.removeQueryEditor(qe)}>
-              <div className="icon-container">
-                <i className="fa fa-close" />
-              </div>
-              {t('Close tab')}
-            </MenuItem>
-            <MenuItem eventKey="2" onClick={() => this.renameTab(qe)}>
-              <div className="icon-container">
-                <i className="fa fa-i-cursor" />
-              </div>
-              {t('Rename tab')}
-            </MenuItem>
-            <MenuItem eventKey="3" onClick={this.toggleLeftBar}>
-              <div className="icon-container">
-                <i className="fa fa-cogs" />
-              </div>
-              {this.state.hideLeftBar ? t('Expand tool bar') : t('Hide tool bar')}
-            </MenuItem>
-            <MenuItem eventKey="4" onClick={() => this.removeAllOtherQueryEditors(qe)}>
-              <div className="icon-container">
-                <i className="fa fa-times-circle-o" />
-              </div>
-              {t('Close all other tabs')}
-            </MenuItem>
-          </DropdownButton>
-        </div>
+        </React.Fragment>
+      );
+      const tabTitle = (
+        <SplitButton
+          bsSize="small"
+          id={'ddbtn-tab-' + i}
+          className="ddbtn-tab"
+          title={title}
+        >
+          <MenuItem eventKey="1" onClick={() => this.removeQueryEditor(qe)}>
+            <div className="icon-container">
+              <i className="fa fa-close" />
+            </div>
+            {t('Close tab')}
+          </MenuItem>
+          <MenuItem eventKey="2" onClick={() => this.renameTab(qe)}>
+            <div className="icon-container">
+              <i className="fa fa-i-cursor" />
+            </div>
+            {t('Rename tab')}
+          </MenuItem>
+          <MenuItem eventKey="3" onClick={this.toggleLeftBar}>
+            <div className="icon-container">
+              <i className="fa fa-cogs" />
+            </div>
+            {this.state.hideLeftBar ? t('Expand tool bar') : t('Hide tool bar')}
+          </MenuItem>
+          <MenuItem eventKey="4" onClick={() => this.removeAllOtherQueryEditors(qe)}>
+            <div className="icon-container">
+              <i className="fa fa-times-circle-o" />
+            </div>
+            {t('Close all other tabs')}
+          </MenuItem>
+        </SplitButton>
       );
       return (
         <Tab key={qe.id} title={tabTitle} eventKey={qe.id}>
-          <div className="panel panel-default">
-            <div className="panel-body">
-              {isSelected && (
-                <SqlEditor
-                  tables={this.props.tables.filter(xt => xt.queryEditorId === qe.id)}
-                  queryEditor={qe}
-                  editorQueries={this.state.queriesArray}
-                  dataPreviewQueries={this.state.dataPreviewQueries}
-                  latestQuery={latestQuery}
-                  database={database}
-                  actions={this.props.actions}
-                  hideLeftBar={this.state.hideLeftBar}
-                  defaultQueryLimit={this.props.defaultQueryLimit}
-                  maxRow={this.props.maxRow}
-                  saveQueryWarning={this.props.saveQueryWarning}
-                />
-              )}
-            </div>
-          </div>
+          {isSelected && (
+            <SqlEditor
+              tables={this.props.tables.filter(xt => xt.queryEditorId === qe.id)}
+              queryEditor={qe}
+              editorQueries={this.state.queriesArray}
+              dataPreviewQueries={this.state.dataPreviewQueries}
+              latestQuery={latestQuery}
+              database={database}
+              actions={this.props.actions}
+              hideLeftBar={this.state.hideLeftBar}
+              defaultQueryLimit={this.props.defaultQueryLimit}
+              maxRow={this.props.maxRow}
+              saveQueryWarning={this.props.saveQueryWarning}
+            />
+          )}
         </Tab>
       );
     });
@@ -264,6 +262,7 @@ class TabbedSqlEditors extends React.PureComponent {
         activeKey={this.props.tabHistory[this.props.tabHistory.length - 1]}
         onSelect={this.handleSelect.bind(this)}
         id="a11y-query-editor-tabs"
+        className="SqlEditorTabs"
       >
         {editors}
         <Tab
@@ -272,6 +271,7 @@ class TabbedSqlEditors extends React.PureComponent {
               <i className="fa fa-plus-circle" />&nbsp;
             </div>
           }
+          className="addEditorTab"
           eventKey="add_tab"
           disabled={this.props.offline}
         />
diff --git a/superset/assets/src/SqlLab/main.less b/superset/assets/src/SqlLab/main.less
index 28755a3..89e5d11 100644
--- a/superset/assets/src/SqlLab/main.less
+++ b/superset/assets/src/SqlLab/main.less
@@ -17,9 +17,11 @@
  * under the License.
  */
 @import "../../stylesheets/less/cosmo/variables.less";
+
 body {
     overflow: hidden;
 }
+
 .inlineBlock {
     display: inline-block;
 }
@@ -32,10 +34,6 @@ body {
 .nopadding {
     padding: 0px;
 }
-.panel.nopadding .panel-body {
-    padding: 0px;
-}
-
 .loading {
     width: 50px;
     margin-top: 15px;
@@ -46,27 +44,19 @@ body {
     width: 100%;
     height: 100%;
 }
-.SqlEditor .header {
-    padding-top: 5px;
-    padding-bottom: 5px;
-}
-
-.scrollbar-container {
-  position: relative;
-  overflow: hidden;
-  width: 100%;
-  height: 100%;
-}
 
-.scrollbar-content {
-  position: absolute;
-  top: 0px;
-  left: 0px;
-  right: 0px;
-  bottom: 0px;
-  overflow: auto;
-  margin-right: 0px;
-  margin-bottom: 0px;
+.tab-content {
+    height: 100%;
+    position: relative;
+    background-color: #fff;
+
+    > .tab-pane {
+        position: absolute;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        left: 0;
+    }
 }
 
 .Workspace .btn-sm {
@@ -82,11 +72,6 @@ div.Workspace {
     height: 100%;
     margin: 0px;
 }
-.SqlEditor .clock {
-    background-color: orange;
-    padding: 5px;
-}
-
 .padded {
     padding: 10px;
 }
@@ -194,10 +179,19 @@ div.Workspace {
     background-color: transparent !important;
 }
 
+#a11y-query-editor-tabs {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
 .SqlLab {
-    .tab-content {
-        height: 100%;
-    }
+    position: absolute;
+    top: 0px;
+    right: 0px;
+    bottom: 0px;
+    left: 0px;
+    padding: 0 10px;
 
     #brace-editor {
         height: calc(100% - 51px);
@@ -212,16 +206,46 @@ div.Workspace {
     }
 }
 
+.SqlEditorTabs li {
+    a:focus {
+        outline: 0;
+    }
+
+    .ddbtn-tab {
+        font-size: inherit;
+        font-weight: bold;
+
+        &:active {
+            background: none;
+        }
+    }
+
+    .dropdown-toggle {
+        padding-top: 2px;
+    }
+}
+
 .SqlEditor {
     display: flex;
     flex-direction: row;
     height: 100%;
+    padding: 10px;
+
+    .clock {
+        background-color: orange;
+        padding: 5px;
+    }
 
     .schemaPane {
-        flex-grow: 1;
+        flex: 0 0 300px;
         transition: all .3s ease-in-out;
     }
 
+    .queryPane {
+        flex: 1 1 auto;
+        padding-left: 10px;
+    }
+
     .schemaPane-enter-done, .schemaPane-exit {
         transform: translateX(0);
     }
@@ -236,12 +260,6 @@ div.Workspace {
         overflow: hidden;
     }
 
-    .queryPane {
-        flex-grow: 8;
-        position: relative;
-        margin-left: 15px;
-    }
-
     .schemaPane-exit-done + .queryPane {
         margin-left: 0;
     }
@@ -258,6 +276,22 @@ div.Workspace {
     }
 }
 
+.SqlEditorLeftBar {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+
+    .divider {
+        border-bottom: 1px solid #f2f2f2;
+        margin: 15px 0;
+    }
+
+    .scrollbar-container {
+        flex: 1 1 auto;
+        overflow: auto;
+    }
+}
+
 .popover{
     max-width:400px;
 }
@@ -276,8 +310,7 @@ div.tablePopover:hover {
     opacity: 1 !important;
 }
 .ResultSetControls {
-    padding-bottom: 3px;
-    padding-top: 3px;
+    padding: 8px 0;
 }
 .ace_editor {
   border: 1px solid #ccc;
@@ -294,14 +327,10 @@ div.tablePopover:hover {
     margin-top: 5px;
 }
 
-.ace_content {
+.ace_scroller {
     background-color: #f4f4f4;
 }
 
-.SouthPane .tab-content {
-    padding-top: 10px;
-}
-
 .TableElement {
     margin-right: 10px;
 }
@@ -346,22 +375,29 @@ a.Link {
     max-width: 500px;
 }
 .SouthPane {
-    margin-top: 10px;
-    position: absolute;
     width: 100%;
-    overflow: auto;
-}
-.nav-tabs > li.active > a,
-.nav-tabs > li.active > a:hover,
-.nav-tabs > li.active > a:focus {
-    padding-bottom: 8px;
-}
-.nav-tabs .dropdown-toggle.btn .caret {
-    margin-top: -12px;
+
+    .SouthPaneTabs {
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+    }
+    .tab-pane {
+        overflow-y: auto;   // scroll the query history pane
+    }
 }
+
 .nav-tabs .ddbtn-tab {
-    margin-left: 5px;
-    padding-right: 0;
+    padding: 0;
+    border: none;
+    background: none;
+
+    &:focus {
+        outline: 0;
+    }
+    &:active {
+        box-shadow: none;
+    }
 }
 .icon-container {
     display: inline-block;
diff --git a/superset/assets/src/components/FilterableTable/FilterableTable.jsx b/superset/assets/src/components/FilterableTable/FilterableTable.jsx
index 03691a1..d557c6a 100644
--- a/superset/assets/src/components/FilterableTable/FilterableTable.jsx
+++ b/superset/assets/src/components/FilterableTable/FilterableTable.jsx
@@ -32,6 +32,8 @@ function getTextWidth(text, font = '12px Roboto') {
   return getTextDimension({ text, style: { font } }).width;
 }
 
+const SCROLL_BAR_HEIGHT = 15;
+
 const propTypes = {
   orderedColumnKeys: PropTypes.array.isRequired,
   data: PropTypes.array.isRequired,
@@ -63,6 +65,7 @@ export default class FilterableTable extends PureComponent {
     this.totalTableWidth = props.orderedColumnKeys
       .map(key => this.widthsForColumnsByKey[key])
       .reduce((curr, next) => curr + next);
+    this.totalTableHeight = props.height;
 
     this.state = {
       sortBy: null,
@@ -93,9 +96,10 @@ export default class FilterableTable extends PureComponent {
   }
 
   fitTableToWidthIfNeeded() {
-    const containerWidth = this.container.getBoundingClientRect().width;
-    if (containerWidth > this.totalTableWidth) {
-      this.totalTableWidth = containerWidth - 2; // accommodates 1px border on container
+    const containerWidth = this.container.clientWidth;
+    if (this.totalTableWidth < containerWidth) {
+      // fit table width if content doesn't fill the width of the container
+      this.totalTableWidth = containerWidth;
     }
     this.setState({ fitted: true });
   }
@@ -178,6 +182,13 @@ export default class FilterableTable extends PureComponent {
       .update(list => sortDirection === SortDirection.DESC ? list.reverse() : list);
     }
 
+    let totalTableHeight = height;
+    if (this.container && this.totalTableWidth > this.container.clientWidth) {
+      // exclude the height of the horizontal scroll bar from the height of the table
+      // if the content overflows
+      totalTableHeight -= SCROLL_BAR_HEIGHT;
+    }
+
     const rowGetter = ({ index }) => this.getDatum(sortedAndFilteredList, index);
     return (
       <div
@@ -189,7 +200,7 @@ export default class FilterableTable extends PureComponent {
           <Table
             ref="Table"
             headerHeight={headerHeight}
-            height={height - 2}
+            height={totalTableHeight}
             overscanRowCount={overscanRowCount}
             rowClassName={this.rowClassName}
             rowHeight={rowHeight}
diff --git a/superset/assets/src/components/FilterableTable/FilterableTableStyles.css b/superset/assets/src/components/FilterableTable/FilterableTableStyles.css
index ddf5f65..5be4a36 100644
--- a/superset/assets/src/components/FilterableTable/FilterableTableStyles.css
+++ b/superset/assets/src/components/FilterableTable/FilterableTableStyles.css
@@ -72,6 +72,3 @@
 }
 .even-row { background: #f2f2f2; }
 .odd-row { background: #ffffff; }
-.filterable-table-container {
-  overflow: auto;
-}
diff --git a/superset/assets/src/components/TableSelector.css b/superset/assets/src/components/TableSelector.css
index 41b8d11..f4098c1 100644
--- a/superset/assets/src/components/TableSelector.css
+++ b/superset/assets/src/components/TableSelector.css
@@ -34,5 +34,5 @@
 }
 .TableSelector .divider {
   border-bottom: 1px solid #f2f2f2;
-  margin: 10px 0;
+  margin: 15px 0;
 }
diff --git a/superset/assets/src/dashboard/stylesheets/dashboard.less b/superset/assets/src/dashboard/stylesheets/dashboard.less
index 509e4a0..3dc9672 100644
--- a/superset/assets/src/dashboard/stylesheets/dashboard.less
+++ b/superset/assets/src/dashboard/stylesheets/dashboard.less
@@ -105,15 +105,15 @@ body {
       border-left-color: white;
     }
 
-    .caret {
-      position: absolute;
-      top: 24px;
-      left: 3px;
-    }
-
     & + .dropdown-menu.dropdown-menu-right {
       min-width: unset;
     }
+
+    .caret {
+      display: inline-block;
+      width: 100%;
+      height: 100%;
+    }
   }
 
   .button-container {
diff --git a/superset/assets/stylesheets/less/cosmo/bootswatch.less b/superset/assets/stylesheets/less/cosmo/bootswatch.less
index d586660..362e745 100644
--- a/superset/assets/stylesheets/less/cosmo/bootswatch.less
+++ b/superset/assets/stylesheets/less/cosmo/bootswatch.less
@@ -24,6 +24,11 @@
 
 .navbar {
   border: none;
+
+  li > a:focus {
+    outline: 0;
+  }
+
   &-inverse {
 
     .badge {
@@ -31,6 +36,11 @@
       color: @brand-primary;
     }
   }
+
+  b.caret {
+    display: inline-block;
+    padding: 0 5px 18px 5px;
+  }
 }
 
 .navbar-inverse {
@@ -92,28 +102,6 @@
   color: @gray-darker;
 }
 
-.dropdown-toggle.btn .caret {
-  margin-left: 6px;
-  margin-top: -21px;
-  margin-right: 6px;
-}
-
-.nav-tabs .dropdown-toggle.btn .caret  {
-  margin-left: -12px;
-  margin-top: -10px;
-}
-
-.navbar-nav .caret,
-.panel-title .caret {
-  margin-left: 6px;
-  margin-top: -24px;
-  margin-right: 6px;
-}
-
-
-
-
-
 // Typography =================================================================
 
 body {
@@ -408,6 +396,10 @@ a.list-group-item {
 
 // Tabs ==============================================================
 
+.nav-tabs > li > a {
+  border-top: 3px solid transparent;
+}
+
 .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus {
   background-color: #fff;
   font-weight: bold;
diff --git a/superset/assets/stylesheets/less/index.less b/superset/assets/stylesheets/less/index.less
index b9a455a..b1fc604 100644
--- a/superset/assets/stylesheets/less/index.less
+++ b/superset/assets/stylesheets/less/index.less
@@ -23,3 +23,22 @@
 @import "./cosmo/bootswatch.less";
 
 @stroke-primary:  @brand-primary;
+
+body {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  display: flex;
+  flex-direction: column;
+}
+
+header {
+  flex: 0 1 auto;
+}
+
+#app {
+  flex: 1 1 auto;
+  position: relative;
+}
diff --git a/superset/assets/stylesheets/superset.less b/superset/assets/stylesheets/superset.less
index ebd648b..587851e 100644
--- a/superset/assets/stylesheets/superset.less
+++ b/superset/assets/stylesheets/superset.less
@@ -21,14 +21,6 @@
 
 @datasource-sql-expression-width: 450px;
 
-body {
-    margin: 0 !important;
-}
-
-.caret {
-    border-top: 4px solid;
-}
-
 .emph {
   font-weight: bold !important;
 }
@@ -413,6 +405,13 @@ table.table-no-hover tr:hover {
     display: inline;
 }
 
+.form-actions-container button {
+  display: flex;
+  .caret {
+    margin: 0 8px;
+  }
+}
+
 .list-container .filter-action {
     margin: 10px 10px 0 10px;
     padding-bottom: 15px;
diff --git a/superset/templates/superset/basic.html b/superset/templates/superset/basic.html
index 28835d1..6c1ff62 100644
--- a/superset/templates/superset/basic.html
+++ b/superset/templates/superset/basic.html
@@ -69,8 +69,8 @@
     {% endblock %}
 
     {% block body %}
-      <div id="app" data-bootstrap="{{ bootstrap_data }}" >
-        <img src="/static/assets/images/loading.gif" style="width: 50px; margin: 10px;">
+      <div id="app" data-bootstrap="{{ bootstrap_data }}">
+        <img src="/static/assets/images/loading.gif" style="width: 50px; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%)">
       </div>
     {% endblock %}