diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 2c64cf241535..81cf62ae78e7 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -8795,14 +8795,11 @@ } }, "@types/react-select": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-3.0.10.tgz", - "integrity": "sha512-oUHXqvbkRhC07q5JjeY6hE+NUqgUM6CyaRXEKYPvMCBqUOuLnYltyhiNx6Jpb+iFpYtNHSQtF4dNJfMdMooKoQ==", - "dev": true, + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-1.3.4.tgz", + "integrity": "sha512-0BwjswNzKBszG5O4xq72W54NrrbmOZvJfaM/Dwru3F6DhvFO9nihMP1IRzXSOJ1qGRCS3VCu9FnBYJ+25lSldw==", "requires": { - "@types/react": "*", - "@types/react-dom": "*", - "@types/react-transition-group": "*" + "@types/react": "*" } }, "@types/react-table": { @@ -8814,15 +8811,6 @@ "@types/react": "*" } }, - "@types/react-transition-group": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.2.4.tgz", - "integrity": "sha512-8DMUaDqh0S70TjkqU0DxOu80tFUiiaS9rxkWip/nb7gtvAsbqOXm02UCmR8zdcjWujgeYPiPNTVpVpKzUDotwA==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, "@types/react-ultimate-pagination": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/react-ultimate-pagination/-/react-ultimate-pagination-1.2.0.tgz", @@ -8849,6 +8837,11 @@ "@types/react": "*" } }, + "@types/rison": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/rison/-/rison-0.0.6.tgz", + "integrity": "sha512-mE3eRK0fpTN/GnNBOIg2tGq2cFhchQXF6fCbrLxus75TgnoOECbdHikr948FGO/UAml7/ZhLMa5FbGkF5PKvmw==" + }, "@types/shortid": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz", @@ -11512,28 +11505,28 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, @@ -11544,14 +11537,14 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, @@ -11562,42 +11555,42 @@ }, "chownr": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "optional": true, @@ -11607,28 +11600,28 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": false, + "resolved": "", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, + "resolved": "", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -11638,14 +11631,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -11662,7 +11655,7 @@ }, "glob": { "version": "7.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, @@ -11677,14 +11670,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, + "resolved": "", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, @@ -11694,7 +11687,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -11704,7 +11697,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -11715,21 +11708,21 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, @@ -11739,14 +11732,14 @@ }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, @@ -11756,14 +11749,14 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true }, "minipass": { "version": "2.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "optional": true, @@ -11774,7 +11767,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": false, + "resolved": "", "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, @@ -11784,7 +11777,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, @@ -11794,14 +11787,14 @@ }, "ms": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true, "optional": true }, "needle": { "version": "2.3.0", - "resolved": false, + "resolved": "", "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "dev": true, "optional": true, @@ -11813,7 +11806,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": false, + "resolved": "", "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, @@ -11832,7 +11825,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -11843,14 +11836,14 @@ }, "npm-bundled": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.1", - "resolved": false, + "resolved": "", "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "dev": true, "optional": true, @@ -11861,7 +11854,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -11874,21 +11867,21 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, @@ -11898,21 +11891,21 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -11923,21 +11916,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": false, + "resolved": "", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, @@ -11959,7 +11952,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -11975,7 +11968,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": false, + "resolved": "", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, @@ -11985,49 +11978,49 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, @@ -12039,7 +12032,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -12049,7 +12042,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, @@ -12059,14 +12052,14 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": false, + "resolved": "", "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, @@ -12082,14 +12075,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, @@ -12099,14 +12092,14 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.0.3", - "resolved": false, + "resolved": "", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true, "optional": true @@ -16437,28 +16430,28 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, @@ -16469,14 +16462,14 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, @@ -16487,42 +16480,42 @@ }, "chownr": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "optional": true, @@ -16532,28 +16525,28 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": false, + "resolved": "", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, + "resolved": "", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -16563,14 +16556,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -16587,7 +16580,7 @@ }, "glob": { "version": "7.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, @@ -16602,14 +16595,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, + "resolved": "", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, @@ -16619,7 +16612,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -16629,7 +16622,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -16640,21 +16633,21 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, @@ -16664,14 +16657,14 @@ }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, @@ -16681,14 +16674,14 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true }, "minipass": { "version": "2.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "optional": true, @@ -16699,7 +16692,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": false, + "resolved": "", "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, @@ -16709,7 +16702,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, @@ -16719,14 +16712,14 @@ }, "ms": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true, "optional": true }, "needle": { "version": "2.3.0", - "resolved": false, + "resolved": "", "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "dev": true, "optional": true, @@ -16738,7 +16731,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": false, + "resolved": "", "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, @@ -16757,7 +16750,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -16768,14 +16761,14 @@ }, "npm-bundled": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.1", - "resolved": false, + "resolved": "", "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "dev": true, "optional": true, @@ -16786,7 +16779,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -16799,21 +16792,21 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, @@ -16823,21 +16816,21 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -16848,21 +16841,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": false, + "resolved": "", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, @@ -16884,7 +16877,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -16900,7 +16893,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": false, + "resolved": "", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, @@ -16910,49 +16903,49 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, @@ -16964,7 +16957,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -16974,7 +16967,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, @@ -16984,14 +16977,14 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": false, + "resolved": "", "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, @@ -17007,14 +17000,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, @@ -17024,14 +17017,14 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.0.3", - "resolved": false, + "resolved": "", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true, "optional": true @@ -31670,6 +31663,11 @@ "inherits": "^2.0.1" } }, + "rison": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/rison/-/rison-0.1.1.tgz", + "integrity": "sha1-TcwFV7JBr/YOdheOd5ITVxPzMSA=" + }, "rst-selector-parser": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 01597d607d62..9602f20f2489 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -92,6 +92,8 @@ "@superset-ui/translation": "^0.12.8", "@types/classnames": "^2.2.9", "@types/react-json-tree": "^0.6.11", + "@types/react-select": "^1.2.1", + "@types/rison": "0.0.6", "@vx/responsive": "^0.0.195", "abortcontroller-polyfill": "^1.1.9", "aphrodite": "^2.3.1", @@ -156,6 +158,7 @@ "redux-thunk": "^2.1.0", "redux-undo": "^1.0.0-beta9-9-7", "regenerator-runtime": "^0.13.3", + "rison": "^0.1.1", "shortid": "^2.2.6", "urijs": "^1.18.10", "use-query-params": "^0.4.5" @@ -177,7 +180,6 @@ "@types/react": "^16.9.23", "@types/react-dom": "^16.9.5", "@types/react-redux": "^7.1.7", - "@types/react-select": "^3.0.10", "@types/react-table": "^7.0.2", "@types/react-ultimate-pagination": "^1.2.0", "@types/yargs": "12 - 15", diff --git a/superset-frontend/src/dashboard/components/PropertiesModal.jsx b/superset-frontend/src/dashboard/components/PropertiesModal.jsx index f266465b8c57..9269299a9c21 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal.jsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal.jsx @@ -20,8 +20,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Row, Col, Button, Modal, FormControl } from 'react-bootstrap'; import Dialog from 'react-bootstrap-dialog'; -import Select from 'react-select'; +import { Async as SelectAsync } from 'react-select'; import AceEditor from 'react-ace'; +import rison from 'rison'; import { t } from '@superset-ui/translation'; import { SupersetClient } from '@superset-ui/connection'; import '../stylesheets/buttons.less'; @@ -55,7 +56,6 @@ class PropertiesModal extends React.PureComponent { json_metadata: '', }, isDashboardLoaded: false, - ownerOptions: null, isAdvancedOpen: false, }; this.onChange = this.onChange.bind(this); @@ -63,10 +63,11 @@ class PropertiesModal extends React.PureComponent { this.onOwnersChange = this.onOwnersChange.bind(this); this.save = this.save.bind(this); this.toggleAdvanced = this.toggleAdvanced.bind(this); + this.loadOwnerOptions = this.loadOwnerOptions.bind(this); + this.handleErrorResponse = this.handleErrorResponse.bind(this); } componentDidMount() { - this.fetchOwnerOptions(); this.fetchDashboardDetails(); } @@ -90,41 +91,42 @@ class PropertiesModal extends React.PureComponent { // datamodel, the dashboard could probably just be passed as a prop. SupersetClient.get({ endpoint: `/api/v1/dashboard/${this.props.dashboardId}`, - }) - .then(response => { - const dashboard = response.json.result; - this.setState(state => ({ - isDashboardLoaded: true, - values: { - ...state.values, - dashboard_title: dashboard.dashboard_title || '', - slug: dashboard.slug || '', - json_metadata: dashboard.json_metadata || '', - }, - })); - const initialSelectedValues = dashboard.owners.map(owner => ({ - value: owner.id, - label: owner.username, - })); - this.onOwnersChange(initialSelectedValues); - }) - .catch(err => console.error(err)); + }).then(response => { + const dashboard = response.json.result; + this.setState(state => ({ + isDashboardLoaded: true, + values: { + ...state.values, + dashboard_title: dashboard.dashboard_title || '', + slug: dashboard.slug || '', + json_metadata: dashboard.json_metadata || '', + }, + })); + const initialSelectedOwners = dashboard.owners.map(owner => ({ + value: owner.id, + label: `${owner.first_name} ${owner.last_name}`, + })); + this.onOwnersChange(initialSelectedOwners); + }, this.handleErrorResponse); } - fetchOwnerOptions() { - SupersetClient.get({ - endpoint: `/api/v1/dashboard/related/owners`, - }) - .then(response => { + loadOwnerOptions(input = '') { + const query = rison.encode({ filter: input }); + return SupersetClient.get({ + endpoint: `/api/v1/dashboard/related/owners?q=${query}`, + }).then( + response => { const options = response.json.result.map(item => ({ value: item.value, label: item.text, })); - this.setState({ - ownerOptions: options, - }); - }) - .catch(err => console.error(err)); + return { options }; + }, + badResponse => { + this.handleErrorResponse(badResponse); + return { options: [] }; + }, + ); } updateFormState(name, value) { @@ -142,6 +144,17 @@ class PropertiesModal extends React.PureComponent { })); } + async handleErrorResponse(response) { + const { error, statusText } = await getClientErrorObject(response); + this.dialog.show({ + title: 'Error', + bsSize: 'medium', + bsStyle: 'danger', + actions: [Dialog.DefaultAction('Ok', () => {}, 'btn-danger')], + body: error || statusText || t('An error has occurred'), + }); + } + save(e) { e.preventDefault(); e.stopPropagation(); @@ -157,38 +170,21 @@ class PropertiesModal extends React.PureComponent { json_metadata: values.json_metadata || null, owners, }), - }) - .then(({ json }) => { - this.props.addSuccessToast(t('The dashboard has been saved')); - this.props.onDashboardSave({ - id: this.props.dashboardId, - title: json.result.dashboard_title, - slug: json.result.slug, - jsonMetadata: json.result.json_metadata, - ownerIds: json.result.owners, - }); - this.props.onHide(); - }) - .catch(response => - getClientErrorObject(response).then(({ error, statusText }) => { - this.dialog.show({ - title: 'Error', - bsSize: 'medium', - bsStyle: 'danger', - actions: [Dialog.DefaultAction('Ok', () => {}, 'btn-danger')], - body: error || statusText || t('An error has occurred'), - }); - }), - ); + }).then(({ json }) => { + this.props.addSuccessToast(t('The dashboard has been saved')); + this.props.onDashboardSave({ + id: this.props.dashboardId, + title: json.result.dashboard_title, + slug: json.result.slug, + jsonMetadata: json.result.json_metadata, + ownerIds: json.result.owners, + }); + this.props.onHide(); + }, this.handleErrorResponse); } render() { - const { - ownerOptions, - values, - isDashboardLoaded, - isAdvancedOpen, - } = this.state; + const { values, isDashboardLoaded, isAdvancedOpen } = this.state; return (
@@ -242,17 +238,19 @@ class PropertiesModal extends React.PureComponent { - true} // options are filtered at the api />

- {t('A list of users who can alter the chart')} + {t( + 'A list of users who can alter the chart. Searchable by name or username.', + )}

diff --git a/superset/charts/api.py b/superset/charts/api.py index feb6e2230da9..761de3c33e93 100644 --- a/superset/charts/api.py +++ b/superset/charts/api.py @@ -43,7 +43,8 @@ ) from superset.constants import RouteMethod from superset.models.slice import Slice -from superset.views.base_api import BaseSupersetModelRestApi +from superset.views.base_api import BaseSupersetModelRestApi, RelatedFieldFilter +from superset.views.filters import FilterRelatedOwners logger = logging.getLogger(__name__) @@ -65,6 +66,8 @@ class ChartRestApi(BaseSupersetModelRestApi): "description", "owners.id", "owners.username", + "owners.first_name", + "owners.last_name", "dashboards.id", "dashboards.dashboard_title", "viz_type", @@ -116,7 +119,9 @@ class ChartRestApi(BaseSupersetModelRestApi): "slices": ("slice_name", "asc"), "owners": ("first_name", "asc"), } - filter_rel_fields_field = {"owners": "first_name"} + related_field_filters = { + "owners": RelatedFieldFilter("first_name", FilterRelatedOwners) + } allowed_rel_fields = {"owners"} @expose("/", methods=["POST"]) diff --git a/superset/dashboards/api.py b/superset/dashboards/api.py index e960c4cbd2b4..9d5c500286d1 100644 --- a/superset/dashboards/api.py +++ b/superset/dashboards/api.py @@ -44,7 +44,8 @@ ) from superset.models.dashboard import Dashboard from superset.views.base import generate_download_headers -from superset.views.base_api import BaseSupersetModelRestApi +from superset.views.base_api import BaseSupersetModelRestApi, RelatedFieldFilter +from superset.views.filters import FilterRelatedOwners logger = logging.getLogger(__name__) @@ -68,6 +69,8 @@ class DashboardRestApi(BaseSupersetModelRestApi): "json_metadata", "owners.id", "owners.username", + "owners.first_name", + "owners.last_name", "changed_by_name", "changed_by_url", "changed_by.username", @@ -113,7 +116,9 @@ class DashboardRestApi(BaseSupersetModelRestApi): "slices": ("slice_name", "asc"), "owners": ("first_name", "asc"), } - filter_rel_fields_field = {"owners": "first_name"} + related_field_filters = { + "owners": RelatedFieldFilter("first_name", FilterRelatedOwners) + } allowed_rel_fields = {"owners"} @expose("/", methods=["POST"]) diff --git a/superset/datasets/api.py b/superset/datasets/api.py index cab625b16995..80ff1d3383fc 100644 --- a/superset/datasets/api.py +++ b/superset/datasets/api.py @@ -42,8 +42,9 @@ get_export_ids_schema, ) from superset.views.base import DatasourceFilter, generate_download_headers -from superset.views.base_api import BaseSupersetModelRestApi +from superset.views.base_api import BaseSupersetModelRestApi, RelatedFieldFilter from superset.views.database.filters import DatabaseFilter +from superset.views.filters import FilterRelatedOwners logger = logging.getLogger(__name__) @@ -90,6 +91,8 @@ class DatasetRestApi(BaseSupersetModelRestApi): "template_params", "owners.id", "owners.username", + "owners.first_name", + "owners.last_name", "columns", "metrics", ] @@ -114,8 +117,10 @@ class DatasetRestApi(BaseSupersetModelRestApi): "metrics", ] openapi_spec_tag = "Datasets" - - filter_rel_fields_field = {"owners": "first_name", "database": "database_name"} + related_field_filters = { + "owners": RelatedFieldFilter("first_name", FilterRelatedOwners), + "database": "database_name", + } filter_rel_fields = {"database": [["id", DatabaseFilter, lambda: []]]} allowed_rel_fields = {"database", "owners"} diff --git a/superset/views/base_api.py b/superset/views/base_api.py index 013b0fd0ecbc..5f49780f90f2 100644 --- a/superset/views/base_api.py +++ b/superset/views/base_api.py @@ -16,12 +16,13 @@ # under the License. import functools import logging -from typing import Dict, Set, Tuple +from typing import cast, Dict, Set, Tuple, Type, Union from flask import request from flask_appbuilder import ModelRestApi from flask_appbuilder.api import expose, protect, rison, safe from flask_appbuilder.models.filters import BaseFilter, Filters +from flask_appbuilder.models.sqla.filters import FilterStartsWith from sqlalchemy.exc import SQLAlchemyError from superset.exceptions import SupersetSecurityException @@ -58,6 +59,14 @@ def wraps(self, pk): # pylint: disable=invalid-name return functools.update_wrapper(wraps, f) +class RelatedFieldFilter: + # data class to specify what filter to use on a /related endpoint + # pylint: disable=too-few-public-methods + def __init__(self, field_name: str, filter_class: Type[BaseFilter]): + self.field_name = field_name + self.filter_class = filter_class + + class BaseSupersetModelRestApi(ModelRestApi): """ Extends FAB's ModelResApi to implement specific superset generic functionality @@ -86,12 +95,12 @@ class BaseSupersetModelRestApi(ModelRestApi): ... } """ # pylint: disable=pointless-string-statement - filter_rel_fields_field: Dict[str, str] = {} + related_field_filters: Dict[str, Union[RelatedFieldFilter, str]] = {} """ - Declare the related field field for filtering:: + Declare the filters for related fields:: - filter_rel_fields_field = { - "": "") + related_fields = { + "": ) } """ # pylint: disable=pointless-string-statement filter_rel_fields: Dict[str, BaseFilter] = {} @@ -125,14 +134,18 @@ def _init_properties(self): super()._init_properties() def _get_related_filter(self, datamodel, column_name: str, value: str) -> Filters: - filter_field = self.filter_rel_fields_field.get(column_name) - filters = datamodel.get_filters([filter_field]) + filter_field = self.related_field_filters.get(column_name) + if isinstance(filter_field, str): + filter_field = RelatedFieldFilter(cast(str, filter_field), FilterStartsWith) + filter_field = cast(RelatedFieldFilter, filter_field) + search_columns = [filter_field.field_name] if filter_field else None + filters = datamodel.get_filters(search_columns) base_filters = self.filter_rel_fields.get(column_name) if base_filters: - filters = filters.add_filter_list(base_filters) - if value: - filters.rest_add_filters( - [{"opr": "sw", "col": filter_field, "value": value}] + filters.add_filter_list(base_filters) + if value and filter_field: + filters.add_filter( + filter_field.field_name, filter_field.filter_class, value ) return filters diff --git a/superset/views/filters.py b/superset/views/filters.py new file mode 100644 index 000000000000..3e4d85a555b5 --- /dev/null +++ b/superset/views/filters.py @@ -0,0 +1,48 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from flask_appbuilder.models.filters import BaseFilter +from flask_babel import lazy_gettext +from sqlalchemy import or_ + +from superset import security_manager + +# pylint: disable=too-few-public-methods + + +class FilterRelatedOwners(BaseFilter): + """ + A filter to allow searching for related owners of a resource. + + Use in the api by adding something like: + related_field_filters = { + "owners": RelatedFieldFilter("first_name", FilterRelatedOwners), + } + """ + + name = lazy_gettext("Owner") + arg_name = "owners" + + def apply(self, query, value): + user_model = security_manager.user_model + like_value = "%" + value + "%" + return query.filter( + or_( + # could be made to handle spaces between names more gracefully + (user_model.first_name + " " + user_model.last_name).ilike(like_value), + user_model.username.ilike(like_value), + ) + ) diff --git a/tests/base_api_tests.py b/tests/base_api_tests.py index 7a0481301a30..112211abb50e 100644 --- a/tests/base_api_tests.py +++ b/tests/base_api_tests.py @@ -158,20 +158,20 @@ def test_get_filter_related_owners(self): API: Test get filter related owners """ self.login(username="admin") - argument = {"filter": "a"} + argument = {"filter": "gamma"} uri = f"api/v1/{self.resource_name}/related/owners?q={prison.dumps(argument)}" rv = self.client.get(uri) self.assertEqual(rv.status_code, 200) response = json.loads(rv.data.decode("utf-8")) - expected_response = { - "count": 2, - "result": [ - {"text": "admin user", "value": 1}, - {"text": "alpha user", "value": 5}, - ], - } - self.assertEqual(response, expected_response) + self.assertEqual(3, response["count"]) + sorted_results = sorted(response["result"], key=lambda value: value["text"]) + expected_results = [ + {"text": "gamma user", "value": 2}, + {"text": "gamma2 user", "value": 3}, + {"text": "gamma_sqllab user", "value": 4}, + ] + self.assertEqual(expected_results, sorted_results) def test_get_related_fail(self): """ diff --git a/tests/chart_api_tests.py b/tests/chart_api_tests.py index 0afda14f24db..e14183fbb967 100644 --- a/tests/chart_api_tests.py +++ b/tests/chart_api_tests.py @@ -486,7 +486,14 @@ def test_get_chart(self): "cache_timeout": None, "dashboards": [], "description": None, - "owners": [{"id": 1, "username": "admin"}], + "owners": [ + { + "id": 1, + "username": "admin", + "first_name": "admin", + "last_name": "user", + } + ], "params": None, "slice_name": "title", "viz_type": None, diff --git a/tests/dashboards/api_tests.py b/tests/dashboards/api_tests.py index 45b588f04cc9..fcd8d11ef281 100644 --- a/tests/dashboards/api_tests.py +++ b/tests/dashboards/api_tests.py @@ -96,7 +96,14 @@ def test_get_dashboard(self): "css": "", "dashboard_title": "title", "json_metadata": "", - "owners": [{"id": 1, "username": "admin"}], + "owners": [ + { + "id": 1, + "username": "admin", + "first_name": "admin", + "last_name": "user", + } + ], "position_json": "", "published": False, "url": f"/superset/dashboard/slug1/",