Trigger update of sources from component

The old trigger in the dispatcher function led to
updates even when the component was no longer mounted
(aka displayed).
This commit is contained in:
René Pfeuffer
2019-12-17 10:25:53 +01:00
parent 8410e7e679
commit 4ef97816e0
2 changed files with 50 additions and 16 deletions

View File

@@ -7,7 +7,7 @@ import styled from "styled-components";
import { binder } from "@scm-manager/ui-extensions"; import { binder } from "@scm-manager/ui-extensions";
import { Repository, File } from "@scm-manager/ui-types"; import { Repository, File } from "@scm-manager/ui-types";
import { ErrorNotification, Loading, Notification } from "@scm-manager/ui-components"; import { ErrorNotification, Loading, Notification } from "@scm-manager/ui-components";
import { getFetchSourcesFailure, isFetchSourcesPending, getSources } from "../modules/sources"; import { getFetchSourcesFailure, isFetchSourcesPending, getSources, fetchSources } from "../modules/sources";
import FileTreeLeaf from "./FileTreeLeaf"; import FileTreeLeaf from "./FileTreeLeaf";
type Props = WithTranslation & { type Props = WithTranslation & {
@@ -19,6 +19,8 @@ type Props = WithTranslation & {
path: string; path: string;
baseUrl: string; baseUrl: string;
updateSources: () => void;
// context props // context props
match: any; match: any;
}; };
@@ -40,6 +42,13 @@ export function findParent(path: string) {
} }
class FileTree extends React.Component<Props> { class FileTree extends React.Component<Props> {
componentDidUpdate(prevProps: Readonly<Props>, prevState: Readonly<{}>, snapshot?: any): void {
const { tree, updateSources } = this.props;
if (tree?._embedded?.children && tree._embedded.children.find(c => c.partialResult)) {
setTimeout(updateSources, 3000);
}
}
render() { render() {
const { error, loading, tree } = this.props; const { error, loading, tree } = this.props;
@@ -123,6 +132,14 @@ class FileTree extends React.Component<Props> {
} }
} }
const mapDispatchToProps = (dispatch: any, ownProps: Props) => {
const { repository, revision, path } = ownProps;
const updateSources = () => dispatch(fetchSources(repository, revision, path, false));
return { updateSources };
};
const mapStateToProps = (state: any, ownProps: Props) => { const mapStateToProps = (state: any, ownProps: Props) => {
const { repository, revision, path } = ownProps; const { repository, revision, path } = ownProps;
@@ -141,5 +158,5 @@ const mapStateToProps = (state: any, ownProps: Props) => {
export default compose( export default compose(
withRouter, withRouter,
connect(mapStateToProps) connect(mapStateToProps, mapDispatchToProps)
)(withTranslation("repos")(FileTree)); )(withTranslation("repos")(FileTree));

View File

@@ -9,28 +9,29 @@ export const FETCH_SOURCES_PENDING = `${FETCH_SOURCES}_${types.PENDING_SUFFIX}`;
export const FETCH_SOURCES_SUCCESS = `${FETCH_SOURCES}_${types.SUCCESS_SUFFIX}`; export const FETCH_SOURCES_SUCCESS = `${FETCH_SOURCES}_${types.SUCCESS_SUFFIX}`;
export const FETCH_SOURCES_FAILURE = `${FETCH_SOURCES}_${types.FAILURE_SUFFIX}`; export const FETCH_SOURCES_FAILURE = `${FETCH_SOURCES}_${types.FAILURE_SUFFIX}`;
export function fetchSources(repository: Repository, revision: string, path: string) { export function fetchSources(
return fetchSourcesWithoutOptionalLoadingState(repository, revision, path, true);
}
export function fetchSourcesWithoutOptionalLoadingState(
repository: Repository, repository: Repository,
revision: string, revision: string,
path: string, path: string,
dispatchLoading: boolean initialLoad = true
) { ) {
return function(dispatch: any) { return function(dispatch: any, getState: () => any) {
if (dispatchLoading) { const state = getState();
if (isFetchSourcesPending(state, repository, revision, path)
|| isUpdateSourcePending(state, repository, revision, path)) {
return;
}
if (initialLoad) {
dispatch(fetchSourcesPending(repository, revision, path)); dispatch(fetchSourcesPending(repository, revision, path));
} else {
dispatch(updateSourcesPending(repository, revision, path))
} }
return apiClient return apiClient
.get(createUrl(repository, revision, path)) .get(createUrl(repository, revision, path))
.then(response => response.json()) .then(response => response.json())
.then((sources: File) => { .then((sources: File) => {
dispatch(fetchSourcesSuccess(repository, revision, path, sources)); dispatch(fetchSourcesSuccess(repository, revision, path, sources));
if (sources._embedded.children && sources._embedded.children.find(c => c.partialResult)) {
setTimeout(() => dispatch(fetchSourcesWithoutOptionalLoadingState(repository, revision, path, false)), 3000);
}
}) })
.catch(err => { .catch(err => {
dispatch(fetchSourcesFailure(repository, revision, path, err)); dispatch(fetchSourcesFailure(repository, revision, path, err));
@@ -56,10 +57,17 @@ export function fetchSourcesPending(repository: Repository, revision: string, pa
}; };
} }
export function updateSourcesPending(repository: Repository, revision: string, path: string): Action {
return {
type: "UPDATE_PENDING",
itemId: createItemId(repository, revision, path)
};
}
export function fetchSourcesSuccess(repository: Repository, revision: string, path: string, sources: File) { export function fetchSourcesSuccess(repository: Repository, revision: string, path: string, sources: File) {
return { return {
type: FETCH_SOURCES_SUCCESS, type: FETCH_SOURCES_SUCCESS,
payload: sources, payload: { updatePending: false, sources },
itemId: createItemId(repository, revision, path) itemId: createItemId(repository, revision, path)
}; };
} }
@@ -91,6 +99,11 @@ export default function reducer(
...state, ...state,
[action.itemId]: action.payload [action.itemId]: action.payload
}; };
} else if (action.itemId && action.type === "UPDATE_PENDING") {
return {
...state,
[action.itemId]: { updatePending: true }}
;
} }
return state; return state;
} }
@@ -113,13 +126,17 @@ export function getSources(
path: string path: string
): File | null | undefined { ): File | null | undefined {
if (state.sources) { if (state.sources) {
return state.sources[createItemId(repository, revision, path)]; return state.sources[createItemId(repository, revision, path)]?.sources;
} }
return null; return null;
} }
export function isFetchSourcesPending(state: any, repository: Repository, revision: string, path: string): boolean { export function isFetchSourcesPending(state: any, repository: Repository, revision: string, path: string): boolean {
return isPending(state, FETCH_SOURCES, createItemId(repository, revision, path)); return state && isPending(state, FETCH_SOURCES, createItemId(repository, revision, path));
}
function isUpdateSourcePending(state: any, repository: Repository, revision: string, path: string): boolean {
return state?.sources[createItemId(repository, revision, path)]?.updatePending;
} }
export function getFetchSourcesFailure( export function getFetchSourcesFailure(