You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@superset.apache.org by GitBox <gi...@apache.org> on 2021/03/24 02:35:35 UTC
[GitHub] [superset] eschutho opened a new pull request #13761: [WIP] add redux to api middleware
eschutho opened a new pull request #13761:
URL: https://github.com/apache/superset/pull/13761
### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
<!--- Skip this if not applicable -->
### TEST PLAN
<!--- What steps should be taken to verify the changes -->
### ADDITIONAL INFORMATION
<!--- Check any relevant boxes with "x" -->
<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
- [ ] Has associated issue:
- [ ] Changes UI
- [ ] Requires DB Migration.
- [ ] Confirm DB Migration upgrade and downgrade tested.
- [ ] Introduces new feature or API
- [ ] Removes existing feature or API
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
[GitHub] [superset] eschutho commented on a change in pull request #13761: [WIP] add redux to api middleware
Posted by GitBox <gi...@apache.org>.
eschutho commented on a change in pull request #13761:
URL: https://github.com/apache/superset/pull/13761#discussion_r600117438
##########
File path: superset-frontend/src/SqlLab/components/ResultSet.tsx
##########
@@ -117,205 +105,59 @@ const ResultSetErrorMessage = styled.div`
padding-top: ${({ theme }) => 4 * theme.gridUnit}px;
`;
-export default class ResultSet extends React.PureComponent<
- ResultSetProps,
- ResultSetState
-> {
- static defaultProps = {
- cache: false,
- csv: true,
- database: {},
- search: true,
- showSql: false,
- visualize: true,
- };
-
- constructor(props: ResultSetProps) {
- super(props);
- this.state = {
- searchText: '',
- showExploreResultsButton: false,
- data: [],
- showSaveDatasetModal: false,
- newSaveDatasetName: this.getDefaultDatasetName(),
- saveDatasetRadioBtnState: DatasetRadioState.SAVE_NEW,
- shouldOverwriteDataSet: false,
- datasetToOverwrite: {},
- saveModalAutocompleteValue: '',
- userDatasetOptions: [],
- };
-
- this.changeSearch = this.changeSearch.bind(this);
- this.fetchResults = this.fetchResults.bind(this);
- this.popSelectStar = this.popSelectStar.bind(this);
- this.reFetchQueryResults = this.reFetchQueryResults.bind(this);
- this.toggleExploreResultsButton = this.toggleExploreResultsButton.bind(
- this,
- );
- this.handleSaveInDataset = this.handleSaveInDataset.bind(this);
- this.handleHideSaveModal = this.handleHideSaveModal.bind(this);
- this.handleDatasetNameChange = this.handleDatasetNameChange.bind(this);
- this.handleSaveDatasetRadioBtnState = this.handleSaveDatasetRadioBtnState.bind(
- this,
- );
- this.handleOverwriteCancel = this.handleOverwriteCancel.bind(this);
- this.handleOverwriteDataset = this.handleOverwriteDataset.bind(this);
- this.handleOverwriteDatasetOption = this.handleOverwriteDatasetOption.bind(
- this,
- );
- this.handleSaveDatasetModalSearch = debounce(
- this.handleSaveDatasetModalSearch.bind(this),
- 1000,
- );
- this.handleFilterAutocompleteOption = this.handleFilterAutocompleteOption.bind(
- this,
- );
- this.handleOnChangeAutoComplete = this.handleOnChangeAutoComplete.bind(
- this,
- );
- this.handleExploreBtnClick = this.handleExploreBtnClick.bind(this);
- }
-
- async componentDidMount() {
- // only do this the first time the component is rendered/mounted
- this.reRunQueryIfSessionTimeoutErrorOnMount();
- const userDatasetsOwned = await this.getUserDatasets();
- this.setState({ userDatasetOptions: userDatasetsOwned });
- }
-
- UNSAFE_componentWillReceiveProps(nextProps: ResultSetProps) {
- // when new results comes in, save them locally and clear in store
+const getDefaultDatasetName = (tab: string | null) =>
+ `${tab} ${moment().format('MM/DD/YYYY HH:mm:ss')}`;
+
+export default function ResultSet({
+ cache = false,
+ csv = true,
+ database = {},
+ search = true,
+ showSql = false,
+ visualize = true,
+ query,
+ ...props
+}: ResultSetProps) {
+ const [searchText, setSearchText] = useState<string>('');
+ const [stateData, setData] = useState<Record<string, any>[]>([]);
+ const [showSaveDatasetModal, setShowSaveDatasetModal] = useState<boolean>(
+ false,
+ );
+ const [newSaveDatasetName, setNewSaveDatasetName] = useState<string>(
+ getDefaultDatasetName(query.tab),
+ );
+ const [
+ saveDatasetRadioBtnState,
+ setSaveDatasetRadioBtnState,
+ ] = useState<DatasetRadioState>(DatasetRadioState.SAVE_NEW);
+ const [shouldOverwriteDataSet, setShouldOverwriteDataSet] = useState<boolean>(
+ false,
+ );
+ const [datasetToOverwrite, setDatasetToOverwrite] = useState<
+ Record<string, any> | { datasetId: string }
+ >({});
+ const [userDatasetOptions, setUserDatasetOptions] = useState<
+ DatasetOptionAutocomplete[]
+ >([]);
+ const cacheRef = useRef(cache);
+ const resultsKeyRef = useRef(query.resultsKey);
+ const putDataset = useDatasetPut({
+ datasetId: datasetToOverwrite.datasetId,
+ overrideColumns: true,
Review comment:
Here's the new hook. This endpoint doesn't return anything, so there's no useSelector in this POC, just useDispatch.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
[GitHub] [superset] stale[bot] commented on pull request #13761: [WIP] add redux to api middleware
Posted by GitBox <gi...@apache.org>.
stale[bot] commented on pull request #13761:
URL: https://github.com/apache/superset/pull/13761#issuecomment-859200769
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. For admin, please label this issue `.pinned` to prevent stale bot from closing the issue.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
[GitHub] [superset] eschutho commented on a change in pull request #13761: [WIP] add redux to api middleware
Posted by GitBox <gi...@apache.org>.
eschutho commented on a change in pull request #13761:
URL: https://github.com/apache/superset/pull/13761#discussion_r600118374
##########
File path: superset-frontend/src/common/hooks/apiResources/apiResources.ts
##########
@@ -67,6 +72,163 @@ const initialState: LoadingState = {
error: null,
};
+const RESOURCE_START = 'RESOURCE_START';
+const RESOURCE_SUCCESS = 'RESOURCE_SUCCESS';
+const RESOURCE_ERROR = 'RESOURCE_FETCH_ERROR';
+
+type FetchStart = {
+ type: typeof RESOURCE_START;
+ clientId: string;
+};
+
+type FetchSuccess<T = any> = {
+ type: typeof RESOURCE_SUCCESS;
+ clientId: string;
+ result: T;
+};
+
+type FetchError = {
+ type: typeof RESOURCE_ERROR;
+ clientId: string;
+ error: Error;
+};
+
+type ResourceAction = FetchStart | FetchSuccess | FetchError;
+
+export function resourcesReducer(
+ state: ResourcesState = initialResourcesState,
+ action: ResourceAction,
+): ResourcesState {
+ switch (action.type) {
+ case RESOURCE_START: {
+ return {
+ ...state,
+ [action.clientId]: {
+ status: ResourceStatus.LOADING,
+ result: null,
+ error: null,
+ },
+ };
+ }
+ case RESOURCE_SUCCESS: {
+ const { clientId, result } = action;
+ return {
+ ...state,
+ [clientId]: {
+ status: ResourceStatus.COMPLETE,
+ result,
+ error: null,
+ },
+ };
+ }
+ case RESOURCE_ERROR: {
+ const { clientId, error } = action as FetchError;
+ return {
+ ...state,
+ [clientId]: {
+ status: ResourceStatus.ERROR,
+ result: null,
+ error,
+ },
+ };
+ }
+ default:
+ return state;
+ }
+}
+
+type ReduxRootState = { apiResources: ResourcesState };
+const selectResource = <RESULT>(clientId: string) => (
+ state: ReduxRootState,
+): Resource<RESULT> | null => state.apiResources[clientId] ?? null;
+
+async function fetchData<RESULT>(
+ dispatch: Dispatch<ResourceAction>,
+ endpoint: string,
+) {
+ const clientId = uuidv1();
+
+ dispatch({
+ type: RESOURCE_START,
+ clientId,
+ });
+
+ const fetchResource = makeApi<{}, RESULT>({
+ method: 'GET',
+ endpoint,
+ });
+
+ try {
+ const result = await fetchResource({});
+ dispatch({
+ type: RESOURCE_SUCCESS,
+ clientId,
+ result,
+ });
+ } catch (error) {
+ dispatch({
+ type: RESOURCE_ERROR,
+ clientId,
+ error,
+ });
+ }
+}
+
+export function useApiFetch<RESULT>(endpoint: string): void {
+ const dispatch = useDispatch<Dispatch<ResourceAction>>();
+ const resource = useSelector(selectResource(endpoint));
+
+ useEffect(() => {
+ if (resource != null) {
+ // fetching already underway/complete, don't duplicate work.
+ return;
+ }
+
+ fetchData<RESULT>(dispatch, endpoint);
+ }, [endpoint, resource, dispatch]);
+}
+
+export function useApiFetchWithStore(endpoint: string) {
+ const dispatch = useDispatch<Dispatch<ResourceAction>>();
+ return async function callResource() {
+ const response = await fetchData(dispatch, endpoint);
Review comment:
we could also return another function that has the useSelector here.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
[GitHub] [superset] eschutho closed pull request #13761: [WIP] add redux to api middleware
Posted by GitBox <gi...@apache.org>.
eschutho closed pull request #13761:
URL: https://github.com/apache/superset/pull/13761
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
[GitHub] [superset] eschutho commented on a change in pull request #13761: [WIP] add redux to api middleware
Posted by GitBox <gi...@apache.org>.
eschutho commented on a change in pull request #13761:
URL: https://github.com/apache/superset/pull/13761#discussion_r600117438
##########
File path: superset-frontend/src/SqlLab/components/ResultSet.tsx
##########
@@ -117,205 +105,59 @@ const ResultSetErrorMessage = styled.div`
padding-top: ${({ theme }) => 4 * theme.gridUnit}px;
`;
-export default class ResultSet extends React.PureComponent<
- ResultSetProps,
- ResultSetState
-> {
- static defaultProps = {
- cache: false,
- csv: true,
- database: {},
- search: true,
- showSql: false,
- visualize: true,
- };
-
- constructor(props: ResultSetProps) {
- super(props);
- this.state = {
- searchText: '',
- showExploreResultsButton: false,
- data: [],
- showSaveDatasetModal: false,
- newSaveDatasetName: this.getDefaultDatasetName(),
- saveDatasetRadioBtnState: DatasetRadioState.SAVE_NEW,
- shouldOverwriteDataSet: false,
- datasetToOverwrite: {},
- saveModalAutocompleteValue: '',
- userDatasetOptions: [],
- };
-
- this.changeSearch = this.changeSearch.bind(this);
- this.fetchResults = this.fetchResults.bind(this);
- this.popSelectStar = this.popSelectStar.bind(this);
- this.reFetchQueryResults = this.reFetchQueryResults.bind(this);
- this.toggleExploreResultsButton = this.toggleExploreResultsButton.bind(
- this,
- );
- this.handleSaveInDataset = this.handleSaveInDataset.bind(this);
- this.handleHideSaveModal = this.handleHideSaveModal.bind(this);
- this.handleDatasetNameChange = this.handleDatasetNameChange.bind(this);
- this.handleSaveDatasetRadioBtnState = this.handleSaveDatasetRadioBtnState.bind(
- this,
- );
- this.handleOverwriteCancel = this.handleOverwriteCancel.bind(this);
- this.handleOverwriteDataset = this.handleOverwriteDataset.bind(this);
- this.handleOverwriteDatasetOption = this.handleOverwriteDatasetOption.bind(
- this,
- );
- this.handleSaveDatasetModalSearch = debounce(
- this.handleSaveDatasetModalSearch.bind(this),
- 1000,
- );
- this.handleFilterAutocompleteOption = this.handleFilterAutocompleteOption.bind(
- this,
- );
- this.handleOnChangeAutoComplete = this.handleOnChangeAutoComplete.bind(
- this,
- );
- this.handleExploreBtnClick = this.handleExploreBtnClick.bind(this);
- }
-
- async componentDidMount() {
- // only do this the first time the component is rendered/mounted
- this.reRunQueryIfSessionTimeoutErrorOnMount();
- const userDatasetsOwned = await this.getUserDatasets();
- this.setState({ userDatasetOptions: userDatasetsOwned });
- }
-
- UNSAFE_componentWillReceiveProps(nextProps: ResultSetProps) {
- // when new results comes in, save them locally and clear in store
+const getDefaultDatasetName = (tab: string | null) =>
+ `${tab} ${moment().format('MM/DD/YYYY HH:mm:ss')}`;
+
+export default function ResultSet({
+ cache = false,
+ csv = true,
+ database = {},
+ search = true,
+ showSql = false,
+ visualize = true,
+ query,
+ ...props
+}: ResultSetProps) {
+ const [searchText, setSearchText] = useState<string>('');
+ const [stateData, setData] = useState<Record<string, any>[]>([]);
+ const [showSaveDatasetModal, setShowSaveDatasetModal] = useState<boolean>(
+ false,
+ );
+ const [newSaveDatasetName, setNewSaveDatasetName] = useState<string>(
+ getDefaultDatasetName(query.tab),
+ );
+ const [
+ saveDatasetRadioBtnState,
+ setSaveDatasetRadioBtnState,
+ ] = useState<DatasetRadioState>(DatasetRadioState.SAVE_NEW);
+ const [shouldOverwriteDataSet, setShouldOverwriteDataSet] = useState<boolean>(
+ false,
+ );
+ const [datasetToOverwrite, setDatasetToOverwrite] = useState<
+ Record<string, any> | { datasetId: string }
+ >({});
+ const [userDatasetOptions, setUserDatasetOptions] = useState<
+ DatasetOptionAutocomplete[]
+ >([]);
+ const cacheRef = useRef(cache);
+ const resultsKeyRef = useRef(query.resultsKey);
+ const putDataset = useDatasetPut({
+ datasetId: datasetToOverwrite.datasetId,
+ overrideColumns: true,
Review comment:
Here's the new hook
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
[GitHub] [superset] eschutho commented on pull request #13761: [WIP] add redux to api middleware
Posted by GitBox <gi...@apache.org>.
eschutho commented on pull request #13761:
URL: https://github.com/apache/superset/pull/13761#issuecomment-805440238
WIP just to show some ideas about the redux middleware for now. Ignore the ResultSet tsx/functional component updates. I'll separate those out into a different file so that it's not mixed in with these changes, but they are a prerequisite.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
[GitHub] [superset] suddjian commented on a change in pull request #13761: [WIP] add redux to api middleware
Posted by GitBox <gi...@apache.org>.
suddjian commented on a change in pull request #13761:
URL: https://github.com/apache/superset/pull/13761#discussion_r600131432
##########
File path: superset-frontend/src/common/hooks/apiResources/apiResources.ts
##########
@@ -67,6 +72,163 @@ const initialState: LoadingState = {
error: null,
};
+const RESOURCE_START = 'RESOURCE_START';
+const RESOURCE_SUCCESS = 'RESOURCE_SUCCESS';
+const RESOURCE_ERROR = 'RESOURCE_FETCH_ERROR';
+
+type FetchStart = {
+ type: typeof RESOURCE_START;
+ clientId: string;
+};
+
+type FetchSuccess<T = any> = {
+ type: typeof RESOURCE_SUCCESS;
+ clientId: string;
+ result: T;
+};
+
+type FetchError = {
+ type: typeof RESOURCE_ERROR;
+ clientId: string;
+ error: Error;
+};
+
+type ResourceAction = FetchStart | FetchSuccess | FetchError;
+
+export function resourcesReducer(
+ state: ResourcesState = initialResourcesState,
+ action: ResourceAction,
+): ResourcesState {
+ switch (action.type) {
+ case RESOURCE_START: {
+ return {
+ ...state,
+ [action.clientId]: {
+ status: ResourceStatus.LOADING,
+ result: null,
+ error: null,
+ },
+ };
+ }
+ case RESOURCE_SUCCESS: {
+ const { clientId, result } = action;
+ return {
+ ...state,
+ [clientId]: {
+ status: ResourceStatus.COMPLETE,
+ result,
+ error: null,
+ },
+ };
+ }
+ case RESOURCE_ERROR: {
+ const { clientId, error } = action as FetchError;
+ return {
+ ...state,
+ [clientId]: {
+ status: ResourceStatus.ERROR,
+ result: null,
+ error,
+ },
+ };
+ }
+ default:
+ return state;
+ }
+}
+
+type ReduxRootState = { apiResources: ResourcesState };
+const selectResource = <RESULT>(clientId: string) => (
+ state: ReduxRootState,
+): Resource<RESULT> | null => state.apiResources[clientId] ?? null;
+
+async function fetchData<RESULT>(
+ dispatch: Dispatch<ResourceAction>,
+ endpoint: string,
+) {
+ const clientId = uuidv1();
+
+ dispatch({
+ type: RESOURCE_START,
+ clientId,
+ });
+
+ const fetchResource = makeApi<{}, RESULT>({
+ method: 'GET',
+ endpoint,
+ });
+
+ try {
+ const result = await fetchResource({});
+ dispatch({
+ type: RESOURCE_SUCCESS,
+ clientId,
+ result,
+ });
+ } catch (error) {
+ dispatch({
+ type: RESOURCE_ERROR,
+ clientId,
+ error,
+ });
+ }
+}
+
+export function useApiFetch<RESULT>(endpoint: string): void {
+ const dispatch = useDispatch<Dispatch<ResourceAction>>();
+ const resource = useSelector(selectResource(endpoint));
+
+ useEffect(() => {
+ if (resource != null) {
+ // fetching already underway/complete, don't duplicate work.
+ return;
+ }
+
+ fetchData<RESULT>(dispatch, endpoint);
+ }, [endpoint, resource, dispatch]);
Review comment:
If `endpoint` were to change, request cancellation might be required to prevent race conditions.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org