diff --git a/client/app/components/QueryBasedParameterInput.jsx b/client/app/components/QueryBasedParameterInput.jsx index b37bcdb4a8..181c8a5a5f 100644 --- a/client/app/components/QueryBasedParameterInput.jsx +++ b/client/app/components/QueryBasedParameterInput.jsx @@ -2,13 +2,15 @@ import { find, isArray, get, first, map, intersection, isEqual, isEmpty } from " import React from "react"; import PropTypes from "prop-types"; import SelectWithVirtualScroll from "@/components/SelectWithVirtualScroll"; +import { connect } from "react-redux"; -export default class QueryBasedParameterInput extends React.Component { +class QueryBasedParameterInput extends React.Component { static propTypes = { parameter: PropTypes.any, // eslint-disable-line react/forbid-prop-types value: PropTypes.any, // eslint-disable-line react/forbid-prop-types mode: PropTypes.oneOf(["default", "multiple"]), queryId: PropTypes.number, + queryResult: PropTypes.any, onSelect: PropTypes.func, className: PropTypes.string, }; @@ -18,6 +20,7 @@ export default class QueryBasedParameterInput extends React.Component { mode: "default", parameter: null, queryId: null, + queryResult: null, onSelect: () => {}, className: "", }; @@ -41,6 +44,7 @@ export default class QueryBasedParameterInput extends React.Component { } if (this.props.value !== prevProps.value) { this.setValue(this.props.value); + this._loadOptions(this.props.queryId, this.props.queryResult); } } @@ -59,11 +63,18 @@ export default class QueryBasedParameterInput extends React.Component { return value; } - async _loadOptions(queryId) { - if (queryId && queryId !== this.state.queryId) { + async _loadOptions(queryId, queryResult) { + if (queryResult?.length >= 1 && queryId && queryId !== this.state.queryId) { this.setState({ loading: true }); - const options = await this.props.parameter.loadDropdownValues(); + let options = await this.props.parameter.loadDropdownValues(); + const arr = [] + queryResult.forEach(obj => { + if(!arr.includes( obj[this.props.parameter.title])){ + arr.push( obj[this.props.parameter.title].toString()) + } + }) + options = options.filter(option => arr.includes(option.value.toString())) // stale queryId check if (this.props.queryId === queryId) { this.setState({ options, loading: false }, () => { @@ -77,8 +88,9 @@ export default class QueryBasedParameterInput extends React.Component { } render() { - const { className, mode, onSelect, queryId, value, ...otherProps } = this.props; + const { className, mode, onSelect, queryId, value, queryResult, ...otherProps } = this.props; const { loading, options } = this.state; + return ( state.QueryData.Data); + const [filters, setFilters] = useState(() => combineFilters(data.filters, props.filters)); // lazy initialization const filtersRef = useRef(); filtersRef.current = filters; diff --git a/client/app/index.js b/client/app/index.js index 9cafdb1f4b..fc5e5af0c6 100644 --- a/client/app/index.js +++ b/client/app/index.js @@ -1,11 +1,19 @@ import React from "react"; import ReactDOM from "react-dom"; +import { Provider } from "react-redux"; import "@/config"; import ApplicationArea from "@/components/ApplicationArea"; import offlineListener from "@/services/offline-listener"; +import { store } from "./store"; -ReactDOM.render(, document.getElementById("application-root"), () => { - offlineListener.init(); -}); +ReactDOM.render( + + + , + document.getElementById("application-root"), + () => { + offlineListener.init(); + } +); diff --git a/client/app/store.js b/client/app/store.js new file mode 100644 index 0000000000..8f463288b9 --- /dev/null +++ b/client/app/store.js @@ -0,0 +1,23 @@ +import { configureStore, createSlice } from "@reduxjs/toolkit"; + +const queryData = { + Data: [], +}; + +const querySlice = createSlice({ + name: "queryData", + initialState: queryData, + reducers: { + getQueryData: (state, { payload }) => { + state.Data = payload; + }, + }, +}); + +const reducer = { + QueryData: querySlice.reducer, +}; + +export const { getQueryData: getQueryAction } = querySlice.actions; + +export const store = configureStore({ reducer }); diff --git a/package-lock.json b/package-lock.json index 7af62f7886..3a33d355e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5072,6 +5072,17 @@ } } }, + "@reduxjs/toolkit": { + "version": "1.6.1", + "resolved": "https://npm.rs21.io:443/@reduxjs%2ftoolkit/-/toolkit-1.6.1.tgz", + "integrity": "sha512-pa3nqclCJaZPAyBhruQtiRwtTjottRrVJqziVZcWzI73i6L3miLTtUyWfauwv08HWtiXLx1xGyGt+yLFfW/d0A==", + "requires": { + "immer": "^9.0.1", + "redux": "^4.1.0", + "redux-thunk": "^2.3.0", + "reselect": "^4.0.0" + } + }, "@samverschueren/stream-to-observable": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", @@ -5352,7 +5363,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", - "dev": true, "requires": { "@types/react": "*", "hoist-non-react-statics": "^3.3.0" @@ -5415,14 +5425,12 @@ "@types/prop-types": { "version": "15.7.3", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", - "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", - "dev": true + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/react": { "version": "16.14.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.2.tgz", "integrity": "sha512-BzzcAlyDxXl2nANlabtT4thtvbbnhee8hMmH/CcJrISDBVcJS1iOsP1f0OAgSdGE0MsY9tqcrb9YoZcOFv9dbQ==", - "dev": true, "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5437,6 +5445,17 @@ "@types/react": "^16" } }, + "@types/react-redux": { + "version": "7.1.18", + "resolved": "https://npm.rs21.io:443/@types%2freact-redux/-/react-redux-7.1.18.tgz", + "integrity": "sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/sinonjs__fake-timers": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", @@ -9468,8 +9487,7 @@ "csstype": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.5.tgz", - "integrity": "sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ==", - "dev": true + "integrity": "sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ==" }, "cubic-hermite": { "version": "1.0.0", @@ -14919,6 +14937,11 @@ "dev": true, "optional": true }, + "immer": { + "version": "9.0.5", + "resolved": "https://npm.rs21.io:443/immer/-/immer-9.0.5.tgz", + "integrity": "sha512-2WuIehr2y4lmYz9gaQzetPR2ECniCifk4ORaQbU3g5EalLt+0IVTosEPJ5BoYl/75ky2mivzdRzV8wWgQGOSYQ==" + }, "immutability-helper": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.9.1.tgz", @@ -21825,6 +21848,47 @@ } } }, + "react-redux": { + "version": "7.2.4", + "resolved": "https://npm.rs21.io:443/react-redux/-/react-redux-7.2.4.tgz", + "integrity": "sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA==", + "requires": { + "@babel/runtime": "^7.12.1", + "@types/react-redux": "^7.1.16", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.13.1" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.14.8", + "resolved": "https://npm.rs21.io:443/@babel%2fruntime/-/runtime-7.14.8.tgz", + "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://npm.rs21.io:443/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://npm.rs21.io:443/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://npm.rs21.io:443/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + } + } + }, "react-refresh": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", @@ -22069,6 +22133,34 @@ "compare-oriented-cell": "^1.0.1" } }, + "redux": { + "version": "4.1.0", + "resolved": "https://npm.rs21.io:443/redux/-/redux-4.1.0.tgz", + "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "requires": { + "@babel/runtime": "^7.9.2" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.14.8", + "resolved": "https://npm.rs21.io:443/@babel%2fruntime/-/runtime-7.14.8.tgz", + "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://npm.rs21.io:443/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + } + } + }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://npm.rs21.io:443/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -22540,6 +22632,11 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "reselect": { + "version": "4.0.0", + "resolved": "https://npm.rs21.io:443/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==" + }, "resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", diff --git a/package.json b/package.json index d473a6cb06..11b4d4b845 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "dependencies": { "@ant-design/icons": "^4.2.1", "@redash/viz": "file:viz-lib", + "@reduxjs/toolkit": "^1.6.1", "ace-builds": "^1.4.12", "antd": "^4.4.3", "axios": "^0.21.1", @@ -71,6 +72,7 @@ "react-ace": "^9.1.1", "react-dom": "^16.14.0", "react-grid-layout": "^0.18.2", + "react-redux": "^7.2.4", "react-resizable": "^1.10.1", "react-virtualized": "^9.21.2", "sql-formatter": "git+https://github.com/getredash/sql-formatter.git",