This is an automated email from the ASF dual-hosted git repository.
rusackas 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 f7f60cc [Chart & Dashboard] improve listview filter ui and add
expandable list support (#9651)
f7f60cc is described below
commit f7f60cc75d4166510727903813499370a0277d73
Author: ʈᵃᵢ <[email protected]>
AuthorDate: Wed Apr 29 21:54:07 2020 -0700
[Chart & Dashboard] improve listview filter ui and add expandable list
support (#9651)
* better styling for select filters and search input
* add emotion babel plugin
* add spec for search input
* fix async select, add beeter error messages
* add error boundary around views
* cleanup and lint
* add expandable list to dashboards
* fix emotion babel config
* fix specs
* remove commented out code
* add selected style
* DRY up styles
* add icons
* fix type
* add apache license
* fix svgs
* fix ExpandableList type
* reduce custom css
* lint
---
superset-frontend/images/icons/cancel-x.svg | 27 +++
superset-frontend/images/icons/search.svg | 29 +++
superset-frontend/package-lock.json | 212 ++++++++++++---------
superset-frontend/package.json | 1 +
.../components/ListView/ListView_spec.jsx | 2 +-
.../javascripts/components/SearchInput_spec.jsx | 92 +++++++++
.../views/dashboardList/DashboardList_spec.jsx | 2 +
superset-frontend/src/components/Button.jsx | 1 +
.../src/components/ExpandableList.tsx | 62 ++++++
.../src/components/ListView/Filters.tsx | 14 +-
.../src/components/ListView/ListViewStyles.less | 7 +
.../src/components/ListView/TableCollection.tsx | 6 +-
superset-frontend/src/components/ListView/types.ts | 8 +-
superset-frontend/src/components/SearchInput.tsx | 87 ++++++++-
superset-frontend/src/components/StyledSelect.tsx | 65 ++++---
.../src/views/chartList/ChartList.tsx | 41 ++--
.../src/views/dashboardList/DashboardList.tsx | 41 +++-
superset-frontend/src/welcome/App.jsx | 17 +-
superset-frontend/webpack.config.js | 9 +
superset/dashboards/api.py | 4 +
20 files changed, 558 insertions(+), 169 deletions(-)
diff --git a/superset-frontend/images/icons/cancel-x.svg
b/superset-frontend/images/icons/cancel-x.svg
new file mode 100644
index 0000000..be42ff5
--- /dev/null
+++ b/superset-frontend/images/icons/cancel-x.svg
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 64 (93537) - https://sketch.com -->
+ <title>Icon / [email protected]</title>
+ <desc>Created with Sketch.</desc>
+ <g id="Icon-/-X-Small" stroke="none" stroke-width="1" fill="none"
fill-rule="evenodd">
+ <polygon id="Shape" points="0 0 24 0 24 24 0 24"></polygon>
+ <path d="M15.71,8.29 C15.5222334,8.10068735 15.2666375,7.99420168
15,7.99420168 C14.7333625,7.99420168 14.4777666,8.10068735 14.29,8.29 L12,10.59
L9.71,8.29 C9.31787782,7.89787785 8.68212219,7.89787787 8.29000003,8.29000003
C7.89787787,8.68212219 7.89787785,9.31787782 8.29,9.71 L10.59,12 L8.29,14.29
C8.10068735,14.4777666 7.99420168,14.7333625 7.99420168,15
C7.99420168,15.2666375 8.10068735,15.5222334 8.29,15.71 C8.4777666,15.8993127
8.73336246,16.0057983 9,16.0057983 C9.26663754 [...]
+ </g>
+</svg>
\ No newline at end of file
diff --git a/superset-frontend/images/icons/search.svg
b/superset-frontend/images/icons/search.svg
new file mode 100644
index 0000000..29e04e3
--- /dev/null
+++ b/superset-frontend/images/icons/search.svg
@@ -0,0 +1,29 @@
+<!--
+ 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.
+-->
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 64 (93537) - https://sketch.com -->
+ <title>Icon / [email protected]</title>
+ <desc>Created with Sketch.</desc>
+ <g id="Icon-/-Search" stroke="none" stroke-width="1" fill="none"
fill-rule="evenodd">
+ <polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
+ <g id="search-alt" transform="translate(4.000000, 4.000000)"
fill="#666666">
+ <path d="M2.0502756,2.0502756 C4.64681622,-0.54626503
8.80843467,-0.6950204 11.5837364,1.70950589 C14.3590382,4.11403218
14.804545,8.25440896 12.6043062,11.1943062 L12.6043062,11.1943062
L12.584,11.214 L16.5643062,15.1943062 C16.7536188,15.3820728
16.8601045,15.6376686 16.8601045,15.9043062 C16.8601045,16.1709437
16.7536188,16.4265396 16.5643062,16.6143062 C16.3765396,16.8036188
16.1209437,16.9101045 15.8543062,16.9101045 C15.5876686,16.9101045
15.3320728,16.8036188 15.144306 [...]
+ </g>
+ </g>
+</svg>
\ No newline at end of file
diff --git a/superset-frontend/package-lock.json
b/superset-frontend/package-lock.json
index afffab3..bb729c9 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -5360,6 +5360,44 @@
"prop-types": "^15.6.0"
}
},
+ "@emotion/babel-plugin-jsx-pragmatic": {
+ "version": "0.1.5",
+ "resolved":
"https://registry.npmjs.org/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.1.5.tgz",
+ "integrity":
"sha512-y+3AJ0SItMDaAgGPVkQBC/S/BaqaPACkQ6MyCI2CUlrjTxKttTVfD3TMtcs7vLEcLxqzZ1xiG0vzwCXjhopawQ==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0"
+ }
+ },
+ "@emotion/babel-preset-css-prop": {
+ "version": "10.0.27",
+ "resolved":
"https://registry.npmjs.org/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-10.0.27.tgz",
+ "integrity":
"sha512-rducrjTpLGDholp0l2l4pXqpzAqYYGMg/x4IteO0db2smf6zegn6RRZdDnbaoMSs63tfPWgo2WukT1/F1gX/AA==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-transform-react-jsx": "^7.3.0",
+ "@babel/runtime": "^7.5.5",
+ "@emotion/babel-plugin-jsx-pragmatic": "^0.1.5",
+ "babel-plugin-emotion": "^10.0.27"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.9.2",
+ "resolved":
"https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
+ "integrity":
"sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.5",
+ "resolved":
"https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+ "integrity":
"sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+ "dev": true
+ }
+ }
+ },
"@emotion/cache": {
"version": "10.0.29",
"resolved":
"https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz",
@@ -11831,7 +11869,7 @@
},
"chownr": {
"version": "1.1.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity":
"sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
"dev": true,
"optional": true
@@ -11866,7 +11904,7 @@
},
"debug": {
"version": "4.1.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity":
"sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"optional": true,
@@ -11897,7 +11935,7 @@
},
"fs-minipass": {
"version": "1.2.5",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
"integrity":
"sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
"dev": true,
"optional": true,
@@ -11931,7 +11969,7 @@
},
"glob": {
"version": "7.1.3",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity":
"sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"dev": true,
"optional": true,
@@ -11963,7 +12001,7 @@
},
"ignore-walk": {
"version": "3.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
"integrity":
"sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
"dev": true,
"optional": true,
@@ -11984,7 +12022,7 @@
},
"inherits": {
"version": "2.0.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true,
"optional": true
@@ -12025,14 +12063,14 @@
},
"minimist": {
"version": "0.0.8",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
"integrity":
"sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"dev": true,
"optional": true,
@@ -12043,7 +12081,7 @@
},
"minizlib": {
"version": "1.2.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz",
"integrity":
"sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
"dev": true,
"optional": true,
@@ -12053,7 +12091,7 @@
},
"mkdirp": {
"version": "0.5.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"optional": true,
@@ -12063,14 +12101,14 @@
},
"ms": {
"version": "2.1.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity":
"sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true,
"optional": true
},
"needle": {
"version": "2.3.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/needle/-/needle-2.3.0.tgz",
"integrity":
"sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==",
"dev": true,
"optional": true,
@@ -12082,7 +12120,7 @@
},
"node-pre-gyp": {
"version": "0.12.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz",
"integrity":
"sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==",
"dev": true,
"optional": true,
@@ -12101,7 +12139,7 @@
},
"nopt": {
"version": "4.0.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"dev": true,
"optional": true,
@@ -12112,14 +12150,14 @@
},
"npm-bundled": {
"version": "1.0.6",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
"integrity":
"sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==",
"dev": true,
"optional": true
},
"npm-packlist": {
"version": "1.4.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz",
"integrity":
"sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==",
"dev": true,
"optional": true,
@@ -12199,7 +12237,7 @@
},
"process-nextick-args": {
"version": "2.0.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity":
"sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true,
"optional": true
@@ -12228,7 +12266,7 @@
},
"readable-stream": {
"version": "2.3.6",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity":
"sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true,
"optional": true,
@@ -12244,7 +12282,7 @@
},
"rimraf": {
"version": "2.6.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity":
"sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"dev": true,
"optional": true,
@@ -12275,7 +12313,7 @@
},
"semver": {
"version": "5.7.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity":
"sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true,
"optional": true
@@ -12335,7 +12373,7 @@
},
"tar": {
"version": "4.4.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
"integrity":
"sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
"dev": true,
"optional": true,
@@ -12375,7 +12413,7 @@
},
"yallist": {
"version": "3.0.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity":
"sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
"dev": true,
"optional": true
@@ -16792,28 +16830,28 @@
"dependencies": {
"abbrev": {
"version": "1.1.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity":
"sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true,
"optional": true
},
"ansi-regex": {
"version": "2.1.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity":
"sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"dev": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.5",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
"integrity":
"sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"dev": true,
"optional": true,
@@ -16824,14 +16862,14 @@
},
"balanced-match": {
"version": "1.0.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity":
"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"optional": true,
@@ -16842,42 +16880,42 @@
},
"chownr": {
"version": "1.1.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity":
"sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
"dev": true,
"optional": true
},
"code-point-at": {
"version": "1.1.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true,
"optional": true
},
"debug": {
"version": "4.1.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity":
"sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"optional": true,
@@ -16887,28 +16925,28 @@
},
"deep-extend": {
"version": "0.6.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity":
"sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"dev": true,
"optional": true
},
"delegates": {
"version": "1.0.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"dev": true,
"optional": true
},
"detect-libc": {
"version": "1.0.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
"dev": true,
"optional": true
},
"fs-minipass": {
"version": "1.2.5",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
"integrity":
"sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
"dev": true,
"optional": true,
@@ -16918,14 +16956,14 @@
},
"fs.realpath": {
"version": "1.0.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true,
"optional": true
},
"gauge": {
"version": "2.7.4",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"dev": true,
"optional": true,
@@ -16942,7 +16980,7 @@
},
"glob": {
"version": "7.1.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity":
"sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"dev": true,
"optional": true,
@@ -16957,14 +16995,14 @@
},
"has-unicode": {
"version": "2.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
"dev": true,
"optional": true
},
"iconv-lite": {
"version": "0.4.24",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity":
"sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true,
"optional": true,
@@ -16974,7 +17012,7 @@
},
"ignore-walk": {
"version": "3.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
"integrity":
"sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
"dev": true,
"optional": true,
@@ -16984,7 +17022,7 @@
},
"inflight": {
"version": "1.0.6",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"optional": true,
@@ -16995,21 +17033,21 @@
},
"inherits": {
"version": "2.0.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity":
"sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"dev": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"optional": true,
@@ -17019,14 +17057,14 @@
},
"isarray": {
"version": "1.0.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true,
"optional": true
},
"minimatch": {
"version": "3.0.4",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity":
"sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"optional": true,
@@ -17036,14 +17074,14 @@
},
"minimist": {
"version": "0.0.8",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
"integrity":
"sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"dev": true,
"optional": true,
@@ -17054,7 +17092,7 @@
},
"minizlib": {
"version": "1.2.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz",
"integrity":
"sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
"dev": true,
"optional": true,
@@ -17064,7 +17102,7 @@
},
"mkdirp": {
"version": "0.5.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"optional": true,
@@ -17074,14 +17112,14 @@
},
"ms": {
"version": "2.1.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity":
"sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true,
"optional": true
},
"needle": {
"version": "2.3.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/needle/-/needle-2.3.0.tgz",
"integrity":
"sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==",
"dev": true,
"optional": true,
@@ -17093,7 +17131,7 @@
},
"node-pre-gyp": {
"version": "0.12.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz",
"integrity":
"sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==",
"dev": true,
"optional": true,
@@ -17112,7 +17150,7 @@
},
"nopt": {
"version": "4.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"dev": true,
"optional": true,
@@ -17123,14 +17161,14 @@
},
"npm-bundled": {
"version": "1.0.6",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
"integrity":
"sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==",
"dev": true,
"optional": true
},
"npm-packlist": {
"version": "1.4.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz",
"integrity":
"sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==",
"dev": true,
"optional": true,
@@ -17141,7 +17179,7 @@
},
"npmlog": {
"version": "4.1.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity":
"sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"dev": true,
"optional": true,
@@ -17154,21 +17192,21 @@
},
"number-is-nan": {
"version": "1.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true,
"optional": true
},
"once": {
"version": "1.4.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"optional": true,
@@ -17178,21 +17216,21 @@
},
"os-homedir": {
"version": "1.0.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true,
"optional": true
},
"os-tmpdir": {
"version": "1.0.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true,
"optional": true
},
"osenv": {
"version": "0.1.5",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
"integrity":
"sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"dev": true,
"optional": true,
@@ -17203,21 +17241,21 @@
},
"path-is-absolute": {
"version": "1.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"optional": true
},
"process-nextick-args": {
"version": "2.0.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity":
"sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true,
"optional": true
},
"rc": {
"version": "1.2.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity":
"sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"dev": true,
"optional": true,
@@ -17239,7 +17277,7 @@
},
"readable-stream": {
"version": "2.3.6",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity":
"sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true,
"optional": true,
@@ -17255,7 +17293,7 @@
},
"rimraf": {
"version": "2.6.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity":
"sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"dev": true,
"optional": true,
@@ -17265,49 +17303,49 @@
},
"safe-buffer": {
"version": "5.1.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity":
"sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity":
"sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true,
"optional": true
},
"sax": {
"version": "1.2.4",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity":
"sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true,
"optional": true
},
"semver": {
"version": "5.7.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity":
"sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true,
"optional": true
},
"set-blocking": {
"version": "2.0.0",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true,
"optional": true
},
"signal-exit": {
"version": "3.0.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true,
"optional": true
},
"string-width": {
"version": "1.0.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"optional": true,
@@ -17319,7 +17357,7 @@
},
"string_decoder": {
"version": "1.1.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity":
"sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"optional": true,
@@ -17329,7 +17367,7 @@
},
"strip-ansi": {
"version": "3.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"optional": true,
@@ -17339,14 +17377,14 @@
},
"strip-json-comments": {
"version": "2.0.1",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true,
"optional": true
},
"tar": {
"version": "4.4.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
"integrity":
"sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
"dev": true,
"optional": true,
@@ -17362,14 +17400,14 @@
},
"util-deprecate": {
"version": "1.0.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true,
"optional": true
},
"wide-align": {
"version": "1.1.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity":
"sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"dev": true,
"optional": true,
@@ -17379,14 +17417,14 @@
},
"wrappy": {
"version": "1.0.2",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
- "resolved": false,
+ "resolved":
"https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity":
"sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
"dev": true,
"optional": true
diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index 66a433b..e591a8b 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -181,6 +181,7 @@
"@babel/preset-env": "^7.8.7",
"@babel/preset-react": "^7.8.3",
"@babel/register": "^7.8.6",
+ "@emotion/babel-preset-css-prop": "^10.0.27",
"@hot-loader/react-dom": "^16.13.0",
"@types/classnames": "^2.2.9",
"@istanbuljs/nyc-config-typescript": "^1.0.1",
diff --git
a/superset-frontend/spec/javascripts/components/ListView/ListView_spec.jsx
b/superset-frontend/spec/javascripts/components/ListView/ListView_spec.jsx
index 637667b..54b29c0 100644
--- a/superset-frontend/spec/javascripts/components/ListView/ListView_spec.jsx
+++ b/superset-frontend/spec/javascripts/components/ListView/ListView_spec.jsx
@@ -384,7 +384,7 @@ describe('ListView with new UI filters', () => {
act(() => {
wrapper
- .find('[data-test="filters-search"]')
+ .find('[data-test="search-input"]')
.last()
.props()
.onBlur();
diff --git a/superset-frontend/spec/javascripts/components/SearchInput_spec.jsx
b/superset-frontend/spec/javascripts/components/SearchInput_spec.jsx
new file mode 100644
index 0000000..da31a32
--- /dev/null
+++ b/superset-frontend/spec/javascripts/components/SearchInput_spec.jsx
@@ -0,0 +1,92 @@
+/**
+ * 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 { shallow } from 'enzyme';
+
+import SearchInput from 'src/components/SearchInput';
+
+describe('SearchInput', () => {
+ const defaultProps = {
+ onSubmit: jest.fn(),
+ onClear: jest.fn(),
+ onChange: jest.fn(),
+ value: '',
+ };
+
+ const factory = overrideProps => {
+ const props = { ...defaultProps, ...(overrideProps || {}) };
+ return shallow(<SearchInput {...props} />);
+ };
+
+ let wrapper;
+
+ beforeAll(() => {
+ wrapper = factory();
+ });
+
+ afterEach(() => {
+ defaultProps.onSubmit.mockClear();
+ defaultProps.onClear.mockClear();
+ defaultProps.onChange.mockClear();
+ });
+
+ it('renders', () => {
+ expect(React.isValidElement(<SearchInput {...defaultProps} />)).toBe(true);
+ });
+
+ const typeSearchInput = value => {
+ wrapper
+ .find('[data-test="search-input"]')
+ .props()
+ .onChange({ currentTarget: { value } });
+ };
+
+ it('submits on enter', () => {
+ typeSearchInput('foo');
+
+ wrapper
+ .find('[data-test="search-input"]')
+ .props()
+ .onKeyDown({ key: 'Enter' });
+
+ expect(defaultProps.onChange).toHaveBeenCalled();
+ expect(defaultProps.onSubmit).toHaveBeenCalled();
+ });
+
+ it('submits on search icon click', () => {
+ typeSearchInput('bar');
+
+ wrapper
+ .find('[data-test="search-submit"]')
+ .props()
+ .onClick();
+
+ expect(defaultProps.onSubmit).toHaveBeenCalled();
+ });
+
+ it('clears on clear icon click', () => {
+ const wrapper2 = factory({ value: 'fizz' });
+ wrapper2
+ .find('[data-test="search-clear"]')
+ .props()
+ .onClick();
+
+ expect(defaultProps.onClear).toHaveBeenCalled();
+ });
+});
diff --git
a/superset-frontend/spec/javascripts/views/dashboardList/DashboardList_spec.jsx
b/superset-frontend/spec/javascripts/views/dashboardList/DashboardList_spec.jsx
index 830c9b9..25e597a 100644
---
a/superset-frontend/spec/javascripts/views/dashboardList/DashboardList_spec.jsx
+++
b/superset-frontend/spec/javascripts/views/dashboardList/DashboardList_spec.jsx
@@ -43,6 +43,7 @@ const mockDashboards = [...new Array(3)].map((_, i) => ({
changed_by_fk: 1,
published: true,
changed_on: new Date().toISOString(),
+ owners: [{ first_name: 'admin', last_name: 'admin_user' }],
}));
fetchMock.get(dashboardsInfoEndpoint, {
@@ -96,6 +97,7 @@ describe('DashboardList', () => {
});
it('edits', () => {
expect(wrapper.find(PropertiesModal)).toHaveLength(0);
+
wrapper
.find('.fa-pencil')
.first()
diff --git a/superset-frontend/src/components/Button.jsx
b/superset-frontend/src/components/Button.jsx
index 80be849..8cd7105 100644
--- a/superset-frontend/src/components/Button.jsx
+++ b/superset-frontend/src/components/Button.jsx
@@ -32,6 +32,7 @@ const propTypes = {
onClick: PropTypes.func,
disabled: PropTypes.bool,
bsSize: PropTypes.string,
+ bsStyle: PropTypes.string,
btnStyles: PropTypes.string,
};
const defaultProps = {
diff --git a/superset-frontend/src/components/ExpandableList.tsx
b/superset-frontend/src/components/ExpandableList.tsx
new file mode 100644
index 0000000..89332d2
--- /dev/null
+++ b/superset-frontend/src/components/ExpandableList.tsx
@@ -0,0 +1,62 @@
+/**
+ * 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, { ReactNode, useState } from 'react';
+// @ts-ignore
+import { css } from '@emotion/core';
+import Button from 'src/components/Button';
+
+interface Props {
+ items: string[] | ReactNode[];
+ display?: number;
+}
+
+function intersperse(arr: any[], sep: string | ReactNode) {
+ if (arr.length === 0) {
+ return [];
+ }
+
+ return arr.slice(1).reduce((xs, x) => xs.concat([sep, x]), [arr[0]]);
+}
+
+export default function ExpandableList({ items, display = 3 }: Props) {
+ const [showingAll, setShowingAll] = useState(false);
+ const toggleShowingAll = () => setShowingAll(!showingAll);
+ const itemsToDisplay = items.slice(0, display);
+ const showMoreAction = items.length > display;
+
+ const lessAction = (
+ <Button bsStyle="link" bsSize="xsmall" onClick={toggleShowingAll}>
+ less
+ </Button>
+ );
+ const moreAction = (
+ <Button bsStyle="link" bsSize="xsmall" onClick={toggleShowingAll}>
+ {items.length - itemsToDisplay.length} more
+ </Button>
+ );
+ return (
+ <span>
+ {showingAll
+ ? intersperse(items, ', ')
+ : intersperse(itemsToDisplay, ', ')}
+ {showMoreAction && ','}
+ {showMoreAction && (showingAll ? lessAction : moreAction)}
+ </span>
+ );
+}
diff --git a/superset-frontend/src/components/ListView/Filters.tsx
b/superset-frontend/src/components/ListView/Filters.tsx
index 6d9ba59..13edfd8 100644
--- a/superset-frontend/src/components/ListView/Filters.tsx
+++ b/superset-frontend/src/components/ListView/Filters.tsx
@@ -36,7 +36,7 @@ interface SelectFilterProps extends BaseFilter {
}
const FilterContainer = styled.div`
- display: inline;
+ display: inline-flex;
margin-right: 8px;
`;
@@ -116,6 +116,10 @@ interface SearchHeaderProps extends BaseFilter {
function SearchFilter({ Header, initialValue, onSubmit }: SearchHeaderProps) {
const [value, setValue] = useState(initialValue || '');
const handleSubmit = () => onSubmit(value);
+ const onClear = () => {
+ setValue('');
+ onSubmit('');
+ };
return (
<FilterContainer>
@@ -126,12 +130,8 @@ function SearchFilter({ Header, initialValue, onSubmit }:
SearchHeaderProps) {
onChange={e => {
setValue(e.currentTarget.value);
}}
- onKeyDown={e => {
- if (e.key === 'Enter') {
- handleSubmit();
- }
- }}
- onBlur={handleSubmit}
+ onSubmit={handleSubmit}
+ onClear={onClear}
/>
</FilterContainer>
);
diff --git a/superset-frontend/src/components/ListView/ListViewStyles.less
b/superset-frontend/src/components/ListView/ListViewStyles.less
index 2a510c6..bbe3d19 100644
--- a/superset-frontend/src/components/ListView/ListViewStyles.less
+++ b/superset-frontend/src/components/ListView/ListViewStyles.less
@@ -16,6 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
+
+@import '~stylesheets/less/variables.less';
+
.superset-list-view {
.filter-dropdown {
margin-top: 20px;
@@ -61,6 +64,10 @@
margin: 0 8px;
}
+ .table-row-selected {
+ background-color: @gray-bg;
+ }
+
.table-cell {
word-break: break-all;
}
diff --git a/superset-frontend/src/components/ListView/TableCollection.tsx
b/superset-frontend/src/components/ListView/TableCollection.tsx
index 863e655..52b561b 100644
--- a/superset-frontend/src/components/ListView/TableCollection.tsx
+++ b/superset-frontend/src/components/ListView/TableCollection.tsx
@@ -69,11 +69,13 @@ export default function TableCollection({
<tbody {...getTableBodyProps()}>
{rows.map(row => {
prepareRow(row);
- const loadingProps = loading ? { className: 'table-row-loader' } :
{};
return (
<tr
{...row.getRowProps()}
- {...loadingProps}
+ className={cx({
+ 'table-row-loader': loading,
+ 'table-row-selected': row.isSelected,
+ })}
onMouseEnter={() => row.setState && row.setState({ hover: true
})}
onMouseLeave={() =>
row.setState && row.setState({ hover: false })
diff --git a/superset-frontend/src/components/ListView/types.ts
b/superset-frontend/src/components/ListView/types.ts
index 76acae3..f8e08a9 100644
--- a/superset-frontend/src/components/ListView/types.ts
+++ b/superset-frontend/src/components/ListView/types.ts
@@ -45,13 +45,7 @@ export type Filters = Filter[];
export interface FilterValue {
id: string;
operator?: string;
- value:
- | string
- | boolean
- | number
- | null
- | undefined
- | { datasource_id: number; datasource_type: string };
+ value: string | boolean | number | null | undefined;
}
export interface FetchDataConfig {
diff --git a/superset-frontend/src/components/SearchInput.tsx
b/superset-frontend/src/components/SearchInput.tsx
index 2a4b8f1..11fba47 100644
--- a/superset-frontend/src/components/SearchInput.tsx
+++ b/superset-frontend/src/components/SearchInput.tsx
@@ -17,13 +17,94 @@
* under the License.
*/
import styled from '@superset-ui/style';
+import React from 'react';
-export default styled.input`
- background-color: ${({ theme }) => theme.colors.secondary.light5};
+interface Props {
+ onSubmit: () => void;
+ onClear: () => void;
+ value: string;
+ onChange: React.EventHandler<React.ChangeEvent<HTMLInputElement>>;
+ placeholder?: string;
+}
+
+const SearchInputWrapper = styled.div`
+ position: relative;
+`;
+
+const StyledInput = styled.input`
+ width: 200px;
background-image: none;
border: 1px solid ${({ theme }) => theme.colors.secondary.light2};
border-radius: 4px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- padding: 4px 8px;
+ padding: 4px 28px;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ &:focus {
+ outline: none;
+ }
+`;
+
+const SearchIcon = styled.div`
+ position: absolute;
+ z-index: 2;
+ display: block;
+ width: 28px;
+ height: 28px;
+ text-align: center;
+ cursor: pointer;
+ background-position: 2px 2px;
+ background-image: url('/static/assets/images/icons/search.svg');
+ background-repeat: no-repeat;
+`;
+
+const ClearIcon = styled.div`
+ position: absolute;
+ z-index: 2;
+ display: block;
+ width: 28px;
+ height: 28px;
+ text-align: center;
+ cursor: pointer;
+ right: 2px;
+ top: 1px;
+ background-position: 2px 2px;
+ background-image: url('/static/assets/images/icons/cancel-x.svg');
+ background-repeat: no-repeat;
`;
+
+export default function SearchInput({
+ onChange,
+ onClear,
+ onSubmit,
+ placeholder = 'Search',
+ value,
+}: Props) {
+ return (
+ <SearchInputWrapper>
+ <SearchIcon
+ data-test="search-submit"
+ role="button"
+ onClick={() => onSubmit()}
+ />
+ <StyledInput
+ data-test="search-input"
+ onKeyDown={e => {
+ if (e.key === 'Enter') {
+ onSubmit();
+ }
+ }}
+ onBlur={() => onSubmit()}
+ placeholder={placeholder}
+ onChange={onChange}
+ value={value}
+ />
+ {value && (
+ <ClearIcon
+ data-test="search-clear"
+ role="button"
+ onClick={() => onClear()}
+ />
+ )}
+ </SearchInputWrapper>
+ );
+}
diff --git a/superset-frontend/src/components/StyledSelect.tsx
b/superset-frontend/src/components/StyledSelect.tsx
index 0573fd6..939bc43 100644
--- a/superset-frontend/src/components/StyledSelect.tsx
+++ b/superset-frontend/src/components/StyledSelect.tsx
@@ -17,54 +17,51 @@
* under the License.
*/
import styled from '@superset-ui/style';
+import { css } from '@emotion/core';
// @ts-ignore
import Select, { Async } from 'react-select';
-export default styled(Select)`
- display: inline;
+const styles = css`
+ display: block;
&.is-focused:not(.is-open) > .Select-control {
border: none;
box-shadow: none;
}
- .Select-control {
- display: inline-table;
- border: none;
- width: 100px;
- &:focus,
- &:hover {
- border: none;
- box-shadow: none;
- }
- .Select-arrow-zone {
- padding-left: 10px;
- }
- }
- .Select-menu-outer {
- margin-top: 0;
- border-bottom-left-radius: 0;
- border-bottom-left-radius: 0;
+ &.is-open > .Select-control .Select-arrow {
+ top: 50%;
}
-`;
-export const AsyncStyledSelect = styled(Async)`
- display: inline;
- &.is-focused:not(.is-open) > .Select-control {
- border: none;
- box-shadow: none;
- }
.Select-control {
- display: inline-table;
+ display: inline-flex;
border: none;
- width: 100px;
+ width: 128px;
+ top: -5px;
&:focus,
&:hover {
border: none;
box-shadow: none;
}
-
+ .Select-multi-value-wrapper {
+ display: flex;
+ }
+ .Select-value {
+ position: relative;
+ padding-right: 2px;
+ max-width: 104px;
+ }
+ .Select-input {
+ padding-left: 0;
+ padding-right: 8px;
+ }
.Select-arrow-zone {
- padding-left: 10px;
+ width: auto;
+ padding: 0;
+ .Select-arrow {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ }
}
}
.Select-menu-outer {
@@ -73,3 +70,11 @@ export const AsyncStyledSelect = styled(Async)`
border-bottom-left-radius: 0;
}
`;
+
+export default styled(Select)`
+ ${styles}
+`;
+
+export const AsyncStyledSelect = styled(Async)`
+ ${styles}
+`;
diff --git a/superset-frontend/src/views/chartList/ChartList.tsx
b/superset-frontend/src/views/chartList/ChartList.tsx
index 5b1c5b4..37b5157 100644
--- a/superset-frontend/src/views/chartList/ChartList.tsx
+++ b/superset-frontend/src/views/chartList/ChartList.tsx
@@ -85,20 +85,11 @@ class ChartList extends React.PureComponent<Props, State> {
this.updateFilters,
);
},
- ([e1, e2]) => {
+ e => {
this.props.addDangerToast(
- t(
- 'An error occurred while fetching charts: %s, %s',
- e1.message,
- e2.message,
- ),
+ t('An error occurred while fetching charts: %s', e.statusText),
);
- if (e1) {
- console.error(e1);
- }
- if (e2) {
- console.error(e2);
- }
+ console.error(e);
},
);
}
@@ -302,7 +293,10 @@ class ChartList extends React.PureComponent<Props, State> {
(err: any) => {
console.error(err);
this.props.addDangerToast(
- t('There was an issue deleting the selected charts'),
+ t(
+ 'There was an issue deleting the selected charts: %s',
+ err.statusText,
+ ),
);
},
);
@@ -319,6 +313,7 @@ class ChartList extends React.PureComponent<Props, State> {
},
loading: true,
});
+
const filterExps = filters
.map(({ id: col, operator: opr, value }) => ({
col,
@@ -329,9 +324,11 @@ class ChartList extends React.PureComponent<Props, State> {
if (
fltr.col === 'datasource' &&
fltr.value &&
- typeof fltr.value === 'object'
+ typeof fltr.value === 'string'
) {
- const { datasource_id: dsId, datasource_type: dsType } = fltr.value;
+ const { datasource_id: dsId, datasource_type: dsType } = JSON.parse(
+ fltr.value,
+ );
return [
...acc,
{ ...fltr, col: 'datasource_id', value: dsId },
@@ -356,8 +353,9 @@ class ChartList extends React.PureComponent<Props, State> {
this.setState({ charts: json.result, chartCount: json.count });
})
.catch(e => {
+ console.log(e.body);
this.props.addDangerToast(
- t('An error occurred while fetching charts: %s', e.message),
+ t('An error occurred while fetching charts: %s', e.statusText),
);
})
.finally(() => {
@@ -376,7 +374,7 @@ class ChartList extends React.PureComponent<Props, State> {
return postProcess ? postProcess(json?.result) : json?.result;
} catch (e) {
this.props.addDangerToast(
- t('An error occurred while fetching chart filters: %s', e.message),
+ t('An error occurred while fetching chart filters: %s', e.statusText),
);
}
return [];
@@ -385,6 +383,10 @@ class ChartList extends React.PureComponent<Props, State> {
convertOwners = (owners: any[]) =>
owners.map(({ text: label, value }) => ({ label, value }));
+ stringifyValues = (datasources: any[]) => {
+ return datasources.map(ds => ({ ...ds, value: JSON.stringify(ds.value) }));
+ };
+
updateFilters = async () => {
const { filterOperators } = this.state;
const fetchOwners = this.createFetchResource(
@@ -419,7 +421,10 @@ class ChartList extends React.PureComponent<Props, State> {
input: 'select',
operator: 'eq',
unfilteredLabel: 'All',
- fetchSelects:
this.createFetchResource('/api/v1/chart/datasources'),
+ fetchSelects: this.createFetchResource(
+ '/api/v1/chart/datasources',
+ this.stringifyValues,
+ ),
},
{
Header: 'Search',
diff --git a/superset-frontend/src/views/dashboardList/DashboardList.tsx
b/superset-frontend/src/views/dashboardList/DashboardList.tsx
index 0137c9e..25569af 100644
--- a/superset-frontend/src/views/dashboardList/DashboardList.tsx
+++ b/superset-frontend/src/views/dashboardList/DashboardList.tsx
@@ -25,6 +25,7 @@ import React from 'react';
import { Panel } from 'react-bootstrap';
import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
import ListView from 'src/components/ListView/ListView';
+import ExpandableList from 'src/components/ExpandableList';
import {
FetchDataConfig,
FilterOperatorMap,
@@ -102,7 +103,11 @@ class DashboardList extends React.PureComponent<Props,
State> {
},
([e1, e2]) => {
this.props.addDangerToast(
- t('An error occurred while fetching Dashboards'),
+ t(
+ 'An error occurred while fetching Dashboards: %s, %s',
+ e1.statusText,
+ e1.statusText,
+ ),
);
if (e1) {
console.error(e1);
@@ -146,6 +151,23 @@ class DashboardList extends React.PureComponent<Props,
State> {
{
Cell: ({
row: {
+ original: { owners },
+ },
+ }: any) => (
+ <ExpandableList
+ items={owners.map(
+ ({ first_name: firstName, last_name: lastName }: any) =>
+ `${firstName} ${lastName}`,
+ )}
+ display={2}
+ />
+ ),
+ Header: t('Owners'),
+ accessor: 'owners',
+ },
+ {
+ Cell: ({
+ row: {
original: {
changed_by_name: changedByName,
changed_by_url: changedByUrl,
@@ -185,10 +207,6 @@ class DashboardList extends React.PureComponent<Props,
State> {
hidden: true,
},
{
- accessor: 'owners',
- hidden: true,
- },
- {
Cell: ({ row: { state, original } }: any) => {
const handleDelete = () => this.handleDashboardDelete(original);
const handleEdit = () => this.openDashboardEditModal(original);
@@ -281,9 +299,9 @@ class DashboardList extends React.PureComponent<Props,
State> {
loading: false,
});
})
- .catch(() => {
+ .catch(e => {
this.props.addDangerToast(
- t('An error occurred while fetching Dashboards'),
+ t('An error occurred while fetching dashboards: %s', e.statusText),
);
});
};
@@ -326,7 +344,10 @@ class DashboardList extends React.PureComponent<Props,
State> {
(err: any) => {
console.error(err);
this.props.addDangerToast(
- t('There was an issue deleting the selected dashboards'),
+ t(
+ 'There was an issue deleting the selected dashboards: ',
+ err.statusText,
+ ),
);
},
);
@@ -371,9 +392,9 @@ class DashboardList extends React.PureComponent<Props,
State> {
.then(({ json = {} }) => {
this.setState({ dashboards: json.result, dashboardCount: json.count });
})
- .catch(() => {
+ .catch(e => {
this.props.addDangerToast(
- t('An error occurred while fetching Dashboards'),
+ t('An error occurred while fetching dashboards: %s', e.statusText),
);
})
.finally(() => {
diff --git a/superset-frontend/src/welcome/App.jsx
b/superset-frontend/src/welcome/App.jsx
index c97dea1..9cef320 100644
--- a/superset-frontend/src/welcome/App.jsx
+++ b/superset-frontend/src/welcome/App.jsx
@@ -27,6 +27,7 @@ import { ThemeProvider } from 'emotion-theming';
import { initFeatureFlags } from 'src/featureFlags';
import { supersetTheme } from '@superset-ui/style';
+import ErrorBoundary from 'src/components/ErrorBoundary';
import Menu from 'src/components/Menu/Menu';
import DashboardList from 'src/views/dashboardList/DashboardList';
import ChartList from 'src/views/chartList/ChartList';
@@ -65,16 +66,24 @@ const App = () => (
<Menu data={menu} />
<Switch>
<Route path="/superset/welcome/">
- <Welcome user={user} />
+ <ErrorBoundary>
+ <Welcome user={user} />
+ </ErrorBoundary>
</Route>
<Route path="/dashboard/list/">
- <DashboardList user={user} />
+ <ErrorBoundary>
+ <DashboardList user={user} />
+ </ErrorBoundary>
</Route>
<Route path="/chart/list/">
- <ChartList user={user} />
+ <ErrorBoundary>
+ <ChartList user={user} />
+ </ErrorBoundary>
</Route>
<Route path="/tablemodelview/list/">
- <DatasetList user={user} />
+ <ErrorBoundary>
+ <DatasetList user={user} />
+ </ErrorBoundary>
</Route>
</Switch>
<ToastPresenter />
diff --git a/superset-frontend/webpack.config.js
b/superset-frontend/webpack.config.js
index 50233b9..ceb514e 100644
--- a/superset-frontend/webpack.config.js
+++ b/superset-frontend/webpack.config.js
@@ -155,6 +155,15 @@ const babelLoader = {
// faster when there are millions of small files
cacheCompression: false,
plugins: ['emotion'],
+ presets: [
+ [
+ '@emotion/babel-preset-css-prop',
+ {
+ autoLabel: true,
+ labelFormat: '[local]',
+ },
+ ],
+ ],
},
};
diff --git a/superset/dashboards/api.py b/superset/dashboards/api.py
index c1d6590..4ff945b 100644
--- a/superset/dashboards/api.py
+++ b/superset/dashboards/api.py
@@ -100,6 +100,10 @@ class DashboardRestApi(BaseSupersetModelRestApi):
"changed_by.username",
"changed_on",
"dashboard_title",
+ "owners.id",
+ "owners.username",
+ "owners.first_name",
+ "owners.last_name",
"id",
"published",
"slug",