Revert "[Code] set loading false if do not need fetch tree (#36083)"

This reverts commit 5f388dc5b0.
This commit is contained in:
spalger 2019-05-10 13:35:42 -07:00
parent cb0335c095
commit 6a013cb82e
9 changed files with 129 additions and 111 deletions

View file

@ -44,7 +44,6 @@ export interface RepoTreePayload {
export const fetchRepoTree = createAction<FetchRepoTreePayload>('FETCH REPO TREE');
export const fetchRepoTreeSuccess = createAction<RepoTreePayload>('FETCH REPO TREE SUCCESS');
export const fetchRepoTreeFailed = createAction<Error>('FETCH REPO TREE FAILED');
export const resetRepoTree = createAction('CLEAR REPO TREE');
export const closeTreePath = createAction<string>('CLOSE TREE PATH');
export const openTreePath = createAction<string>('OPEN TREE PATH');

View file

@ -44,6 +44,7 @@ test('render correctly', () => {
location={location}
closeTreePath={mockFunction}
openTreePath={mockFunction}
fetchRepoTree={mockFunction}
/>
)
.toJSON();

View file

@ -11,7 +11,7 @@ import classes from 'classnames';
import { connect } from 'react-redux';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { FileTree as Tree, FileTreeItemType } from '../../../model';
import { closeTreePath, openTreePath } from '../../actions';
import { closeTreePath, fetchRepoTree, FetchRepoTreePayload, openTreePath } from '../../actions';
import { EuiSideNavItem, MainRouteParams, PathTypes } from '../../common/types';
import { RootState } from '../../reducers';
import { encodeRevisionString } from '../../utils/url';
@ -20,7 +20,9 @@ interface Props extends RouteComponentProps<MainRouteParams> {
node?: Tree;
closeTreePath: (paths: string) => void;
openTreePath: (paths: string) => void;
fetchRepoTree: (p: FetchRepoTreePayload) => void;
openedPaths: string[];
treeLoading?: boolean;
}
export class CodeFileTree extends React.Component<Props> {
@ -31,6 +33,16 @@ export class CodeFileTree extends React.Component<Props> {
}
}
public fetchTree(path = '', isDir: boolean) {
const { resource, org, repo, revision } = this.props.match.params;
this.props.fetchRepoTree({
uri: `${resource}/${org}/${repo}`,
revision,
path: path || '',
isDir,
});
}
public onClick = (node: Tree) => {
const { resource, org, repo, revision, path } = this.props.match.params;
if (!(path === node.path)) {
@ -241,9 +253,11 @@ export class CodeFileTree extends React.Component<Props> {
const mapStateToProps = (state: RootState) => ({
node: state.file.tree,
openedPaths: state.file.openedPaths,
treeLoading: state.file.rootFileTreeLoading,
});
const mapDispatchToProps = {
fetchRepoTree,
closeTreePath,
openTreePath,
};

View file

@ -52,9 +52,9 @@ interface Props extends RouteComponentProps<MainRouteParams> {
loadingCommits: boolean;
onSearchScopeChanged: (s: SearchScope) => void;
repoScope: string[];
fileTreeLoadingPaths: string[];
searchOptions: SearchOptions;
currentRepository?: Repository;
fileTreeLoading: boolean;
}
const LANG_MD = 'markdown';
@ -272,7 +272,7 @@ class CodeContent extends React.PureComponent<Props> {
return this.renderProgress();
}
const { file, match, tree, fileTreeLoadingPaths } = this.props;
const { file, match, tree, fileTreeLoading } = this.props;
const { path, pathType, resource, org, repo, revision } = match.params;
const repoUri = `${resource}/${org}/${repo}`;
switch (pathType) {
@ -280,7 +280,7 @@ class CodeContent extends React.PureComponent<Props> {
const node = this.findNode(path ? path.split('/') : [], tree);
return (
<div className="codeContainer__directoryView">
<Directory node={node} loading={fileTreeLoadingPaths.includes(path)} />
<Directory node={node} loading={fileTreeLoading} />
<CommitHistory
repoUri={repoUri}
header={
@ -388,7 +388,7 @@ const mapStateToProps = (state: RootState) => ({
isNotFound: state.file.isNotFound,
file: state.file.file,
tree: state.file.tree,
fileTreeLoadingPaths: state.file.fileTreeLoadingPaths,
fileTreeLoading: state.file.fileTreeLoading,
currentTree: currentTreeSelector(state),
branches: state.file.branches,
hasMoreCommits: hasMoreCommitsSelector(state),

View file

@ -69,7 +69,7 @@ class CodeMain extends React.Component<Props> {
}
const mapStateToProps = (state: RootState) => ({
loadingFileTree: state.file.fileTreeLoadingPaths.includes(''),
loadingFileTree: state.file.rootFileTreeLoading,
loadingStructureTree: state.symbol.loading,
hasStructure: structureSelector(state).length > 0 && !state.symbol.error,
languageServerInitializing: state.symbol.languageServerInitializing,

View file

@ -33,6 +33,8 @@ import {
export interface FileState {
tree: FileTree;
fileTreeLoading: boolean;
rootFileTreeLoading: boolean;
openedPaths: string[];
branches: ReferenceInfo[];
tags: ReferenceInfo[];
@ -44,7 +46,6 @@ export interface FileState {
currentPath: string;
loadingCommits: boolean;
commitsFullyLoaded: { [path: string]: boolean };
fileTreeLoadingPaths: string[];
}
const initialState: FileState = {
@ -55,7 +56,8 @@ const initialState: FileState = {
type: FileTreeItemType.Directory,
},
openedPaths: [],
fileTreeLoadingPaths: [''],
rootFileTreeLoading: true,
fileTreeLoading: false,
branches: [],
tags: [],
commits: [],
@ -107,13 +109,12 @@ export const file = handleActions(
[String(fetchRepoTree)]: (state: FileState, action: any) =>
produce(state, draft => {
draft.currentPath = action.payload.path;
draft.fileTreeLoadingPaths.push(action.payload!.path);
draft.fileTreeLoading = true;
}),
[String(fetchRepoTreeSuccess)]: (state: FileState, action: Action<RepoTreePayload>) =>
produce<FileState>(state, (draft: FileState) => {
draft.fileTreeLoadingPaths = draft.fileTreeLoadingPaths.filter(
p => p !== action.payload!.path && p !== ''
);
draft.fileTreeLoading = false;
draft.rootFileTreeLoading = false;
const { tree, path, withParents } = action.payload!;
if (withParents || path === '/' || path === '') {
draft.tree = mergeNode(draft.tree, tree);
@ -137,11 +138,10 @@ export const file = handleActions(
draft.tree = initialState.tree;
draft.openedPaths = initialState.openedPaths;
}),
[String(fetchRepoTreeFailed)]: (state: FileState, action: Action<any>) =>
[String(fetchRepoTreeFailed)]: (state: FileState) =>
produce(state, draft => {
draft.fileTreeLoadingPaths = draft.fileTreeLoadingPaths.filter(
p => p !== action.payload!.path && p !== ''
);
draft.fileTreeLoading = false;
draft.rootFileTreeLoading = false;
}),
[String(openTreePath)]: (state: FileState, action: Action<any>) =>
produce<FileState>(state, (draft: FileState) => {

View file

@ -40,7 +40,6 @@ import {
lastRequestPathSelector,
refUrlSelector,
repoScopeSelector,
createTreeSelector,
} from '../selectors';
import { history } from '../utils/url';
import { mainRoutePattern } from './patterns';
@ -197,27 +196,15 @@ function* handleMainRouteChange(action: Action<Match>) {
.slice(0, -1)
.join('/');
yield put(openTreePath(openPath));
function isTreeLoaded(isDirectory: boolean, targetTree: FileTree | null) {
if (!isDirectory) {
return !!targetTree;
} else if (!targetTree) {
return false;
} else {
return targetTree.children && targetTree.children.length > 0;
}
}
const targetTree: FileTree | null = yield select(createTreeSelector(file || ''));
if (!isTreeLoaded(isDir, targetTree)) {
yield put(
fetchRepoTree({
uri: repoUri,
revision,
path: file || '',
parents: getPathOfTree(tree, (file || '').split('/')) === null,
isDir,
})
);
}
yield put(
fetchRepoTree({
uri: repoUri,
revision,
path: file || '',
parents: getPathOfTree(tree, (file || '').split('/')) === null,
isDir,
})
);
const uri = toCanonicalUrl({
repoUri,
file,

View file

@ -10,6 +10,7 @@ import { kfetch } from 'ui/kfetch';
import Url from 'url';
import { call, put, select, takeEvery, takeLatest } from 'redux-saga/effects';
import { FileTree } from '../../model';
import {
fetchDirectory,
fetchDirectoryFailed,
@ -40,34 +41,48 @@ import {
setNotFound,
} from '../actions';
import { RootState } from '../reducers';
import { treeCommitsSelector } from '../selectors';
import { treeCommitsSelector, createTreeSelector } from '../selectors';
import { repoRoutePattern } from './patterns';
import { FileTree } from '../../model';
function* handleFetchRepoTree(action: Action<FetchRepoTreePayload>) {
try {
const tree = yield call(requestRepoTree, action.payload!);
(tree.children || []).sort((a: FileTree, b: FileTree) => {
const typeDiff = a.type - b.type;
if (typeDiff === 0) {
return a.name > b.name ? 1 : -1;
const { uri, revision, path, parents, isDir } = action.payload!;
if (path && isDir) {
const tree = yield select(createTreeSelector(path));
if (tree) {
const { children } = tree;
// do not request file tree if this tree exists and its children are not empty
if (!children || children.length === 0) {
yield call(fetchPath, { uri, revision, path, parents, isDir });
}
} else {
return -typeDiff;
yield call(fetchPath, { uri, revision, path, parents, isDir });
}
});
tree.repoUri = action.payload!.uri;
yield put(
fetchRepoTreeSuccess({
tree,
path: action.payload!.path,
withParents: action.payload!.parents,
})
);
} else {
yield call(fetchPath, action.payload!);
}
} catch (err) {
yield put(fetchRepoTreeFailed({ ...err, path: action.payload!.path }));
yield put(fetchRepoTreeFailed(err));
}
}
function* fetchPath(payload: FetchRepoTreePayload) {
const update: FileTree = yield call(requestRepoTree, payload);
(update.children || []).sort((a, b) => {
const typeDiff = a.type - b.type;
if (typeDiff === 0) {
return a.name > b.name ? 1 : -1;
} else {
return -typeDiff;
}
});
update.repoUri = payload.uri;
yield put(
fetchRepoTreeSuccess({ tree: update, path: payload.path, withParents: payload.parents })
);
return update;
}
interface FileTreeQuery {
parents?: boolean;
limit: number;

View file

@ -194,70 +194,72 @@ export default function exploreRepositoryFunctonalTests({
});
});
it('Click file/directory on the right panel', async () => {
log.debug('Click file/directory on the right panel');
// TODO(qianliang): blocked by https://github.com/elastic/code/issues/1163
// it('Click file/directory on the right panel', async () => {
// log.debug('Click file/directory on the right panel');
// Wait the file tree to be rendered and click the 'src' folder on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-src')).to.be(true);
});
// // Wait the file tree to be rendered and click the 'src' folder on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-src')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-src');
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-models')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-src');
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-models')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-models');
// Then the 'models' folder on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-User.ts')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-models');
// // Then the 'models' folder on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-User.ts')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-User.ts');
// Then the 'User.ts' file on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeSourceViewer')).to.be(true);
});
});
// await testSubjects.click('codeFileExplorerNode-User.ts');
// // Then the 'User.ts' file on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeSourceViewer')).to.be(true);
// });
// });
it('Navigate source file via structure tree', async () => {
log.debug('Navigate source file via structure tree');
// Wait the file tree to be rendered and click the 'src' folder on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-src')).to.be(true);
});
// TODO(qianliang): blocked by https://github.com/elastic/code/issues/1163
// it('Navigate source file via structure tree', async () => {
// log.debug('Navigate source file via structure tree');
// // Wait the file tree to be rendered and click the 'src' folder on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-src')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-src');
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-models')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-src');
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-models')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-models');
// Then the 'models' folder on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-User.ts')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-models');
// // Then the 'models' folder on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-User.ts')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-User.ts');
// Then the 'User.ts' file on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeSourceViewer')).to.be(true);
expect(await testSubjects.exists('codeStructureTreeTab')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-User.ts');
// // Then the 'User.ts' file on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeSourceViewer')).to.be(true);
// expect(await testSubjects.exists('codeStructureTreeTab')).to.be(true);
// });
// Click the structure tree tab
await testSubjects.click('codeStructureTreeTab');
await retry.tryForTime(300000, async () => {
expect(await testSubjects.exists('codeStructureTreeNode-User')).to.be(true);
// // Click the structure tree tab
// await testSubjects.click('codeStructureTreeTab');
// await retry.tryForTime(300000, async () => {
// expect(await testSubjects.exists('codeStructureTreeNode-User')).to.be(true);
await testSubjects.click('codeStructureTreeNode-User');
await retry.tryForTime(120000, async () => {
const currentUrl: string = await browser.getCurrentUrl();
log.info(`Jump to url: ${currentUrl}`);
expect(currentUrl.indexOf('src/models/User.ts!L92:6') > 0).to.be(true);
});
});
});
// await testSubjects.click('codeStructureTreeNode-User');
// await retry.tryForTime(120000, async () => {
// const currentUrl: string = await browser.getCurrentUrl();
// log.info(`Jump to url: ${currentUrl}`);
// expect(currentUrl.indexOf('src/models/User.ts!L92:6') > 0).to.be(true);
// });
// });
// });
});
});
}