mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
fix(code/frontend): repo not exists error page
This commit is contained in:
parent
737a4df891
commit
94f5de9542
11 changed files with 71 additions and 18 deletions
|
@ -69,7 +69,8 @@ export const fetchFileFailed = createAction<Error>('FETCH FILE ERROR');
|
|||
export const fetchDirectory = createAction<FetchRepoTreePayload>('FETCH REPO DIR');
|
||||
export const fetchDirectorySuccess = createAction<FileTree>('FETCH REPO DIR SUCCESS');
|
||||
export const fetchDirectoryFailed = createAction<Error>('FETCH REPO DIR FAILED');
|
||||
export const setNotFound = createAction<boolean>('SET NOT FOUND');
|
||||
export const setNotFound = createAction<boolean>('SET FILE NOT FOUND');
|
||||
export const dirNotFound = createAction<string>('DIR NOT FOUND');
|
||||
|
||||
export const fetchTreeCommits = createAction<FetchFilePayload>('FETCH TREE COMMITS');
|
||||
export const fetchTreeCommitsSuccess = createAction<{
|
||||
|
|
|
@ -40,6 +40,7 @@ export const fetchRepoConfigFailed = createAction<Error>('FETCH REPO CONFIGS FAI
|
|||
export const initRepoCommand = createAction<string>('INIT REPO CMD');
|
||||
|
||||
export const gotoRepo = createAction<string>('GOTO REPO');
|
||||
export const gotoRepoFailed = createAction('GOTO REPO FAILED');
|
||||
|
||||
export const switchLanguageServer = createAction<RepoConfigPayload>('SWITCH LANGUAGE SERVER');
|
||||
export const switchLanguageServerSuccess = createAction('SWITCH LANGUAGE SERVER SUCCESS');
|
||||
|
|
|
@ -18,8 +18,6 @@ import { Route } from './route';
|
|||
import * as ROUTES from './routes';
|
||||
import { Search } from './search_page/search';
|
||||
|
||||
const Empty = () => null;
|
||||
|
||||
const RooComponent = (props: { setupOk?: boolean }) => {
|
||||
if (props.setupOk) {
|
||||
return <Redirect to={'/admin'} />;
|
||||
|
@ -33,6 +31,8 @@ const mapStateToProps = (state: RootState) => ({
|
|||
|
||||
const Root = connect(mapStateToProps)(RooComponent);
|
||||
|
||||
const Empty = () => null;
|
||||
|
||||
export const App = () => {
|
||||
return (
|
||||
<Router>
|
||||
|
|
|
@ -52,6 +52,7 @@ interface Props extends RouteComponentProps<MainRouteParams> {
|
|||
loadingCommits: boolean;
|
||||
onSearchScopeChanged: (s: SearchScope) => void;
|
||||
repoScope: string[];
|
||||
notFoundDirs: string[];
|
||||
searchOptions: SearchOptions;
|
||||
fileTreeLoading: boolean;
|
||||
query: string;
|
||||
|
@ -265,15 +266,15 @@ class CodeContent extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
public renderContent() {
|
||||
if (this.props.isNotFound) {
|
||||
const { file, match, tree, fileTreeLoading, isNotFound, notFoundDirs } = this.props;
|
||||
const { path, pathType, resource, org, repo, revision } = match.params;
|
||||
if (isNotFound || notFoundDirs.includes(path || '')) {
|
||||
return <NotFound />;
|
||||
}
|
||||
if (this.shouldRenderProgress()) {
|
||||
return this.renderProgress();
|
||||
}
|
||||
|
||||
const { file, match, tree, fileTreeLoading } = this.props;
|
||||
const { path, pathType, resource, org, repo, revision } = match.params;
|
||||
const repoUri = `${resource}/${org}/${repo}`;
|
||||
switch (pathType) {
|
||||
case PathTypes.tree:
|
||||
|
@ -386,6 +387,7 @@ class CodeContent extends React.PureComponent<Props> {
|
|||
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
isNotFound: state.file.isNotFound,
|
||||
notFoundDirs: state.file.notFoundDirs,
|
||||
file: state.file.file,
|
||||
tree: state.file.tree,
|
||||
fileTreeLoading: state.file.fileTreeLoading,
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ErrorIcon } from '../shared/icons';
|
|||
|
||||
export const ErrorPanel = (props: { title: ReactNode; content: string }) => {
|
||||
return (
|
||||
<div className="codePanel__error">
|
||||
<div className="codePanel__error" data-test-subj="codeNotFoundErrorPage">
|
||||
<EuiPanel>
|
||||
<EuiSpacer />
|
||||
<EuiText textAlign="center">
|
||||
|
|
|
@ -31,6 +31,7 @@ import {
|
|||
setNotFound,
|
||||
fetchRootRepoTreeSuccess,
|
||||
fetchRootRepoTreeFailed,
|
||||
dirNotFound,
|
||||
} from '../actions';
|
||||
|
||||
export interface FileState {
|
||||
|
@ -38,6 +39,8 @@ export interface FileState {
|
|||
fileTreeLoading: boolean;
|
||||
rootFileTreeLoading: boolean;
|
||||
openedPaths: string[];
|
||||
// store not found directory as an array to calculate `notFound` flag by finding whether path is in this array
|
||||
notFoundDirs: string[];
|
||||
branches: ReferenceInfo[];
|
||||
tags: ReferenceInfo[];
|
||||
commits: CommitInfo[];
|
||||
|
@ -58,6 +61,7 @@ const initialState: FileState = {
|
|||
type: FileTreeItemType.Directory,
|
||||
},
|
||||
openedPaths: [],
|
||||
notFoundDirs: [],
|
||||
rootFileTreeLoading: true,
|
||||
fileTreeLoading: false,
|
||||
branches: [],
|
||||
|
@ -117,6 +121,7 @@ export const file = handleActions(
|
|||
produce<FileState>(state, (draft: FileState) => {
|
||||
draft.fileTreeLoading = false;
|
||||
draft.rootFileTreeLoading = false;
|
||||
draft.notFoundDirs = draft.notFoundDirs.filter(dir => dir !== action.payload!.path);
|
||||
const { tree, path, withParents } = action.payload!;
|
||||
if (withParents || path === '/' || path === '') {
|
||||
draft.tree = mergeNode(draft.tree, tree);
|
||||
|
@ -144,6 +149,10 @@ export const file = handleActions(
|
|||
produce<FileState>(state, (draft: FileState) => {
|
||||
draft.rootFileTreeLoading = false;
|
||||
}),
|
||||
[String(dirNotFound)]: (state: FileState, action: any) =>
|
||||
produce<FileState>(state, (draft: FileState) => {
|
||||
draft.notFoundDirs.push(action.payload);
|
||||
}),
|
||||
[String(resetRepoTree)]: (state: FileState) =>
|
||||
produce<FileState>(state, (draft: FileState) => {
|
||||
draft.tree = initialState.tree;
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
loadConfigsSuccess,
|
||||
loadRepoSuccess,
|
||||
loadRepoFailed,
|
||||
loadRepo,
|
||||
} from '../actions';
|
||||
|
||||
export enum ToastType {
|
||||
|
@ -41,6 +42,7 @@ export interface RepositoryState {
|
|||
toastType?: ToastType;
|
||||
projectConfigs: { [key: string]: RepositoryConfig };
|
||||
currentRepository?: Repository;
|
||||
repoNotFound: boolean;
|
||||
}
|
||||
|
||||
const initialState: RepositoryState = {
|
||||
|
@ -49,6 +51,7 @@ const initialState: RepositoryState = {
|
|||
importLoading: false,
|
||||
showToast: false,
|
||||
projectConfigs: {},
|
||||
repoNotFound: false,
|
||||
};
|
||||
|
||||
export const repository = handleActions(
|
||||
|
@ -116,13 +119,20 @@ export const repository = handleActions(
|
|||
produce<RepositoryState>(state, draft => {
|
||||
draft.projectConfigs = action.payload;
|
||||
}),
|
||||
[String(loadRepo)]: (state: RepositoryState, action: Action<any>) =>
|
||||
produce<RepositoryState>(state, draft => {
|
||||
draft.currentRepository = undefined;
|
||||
draft.repoNotFound = false;
|
||||
}),
|
||||
[String(loadRepoSuccess)]: (state: RepositoryState, action: Action<any>) =>
|
||||
produce<RepositoryState>(state, draft => {
|
||||
draft.currentRepository = action.payload;
|
||||
draft.repoNotFound = false;
|
||||
}),
|
||||
[String(loadRepoFailed)]: (state: RepositoryState, action: Action<any>) =>
|
||||
produce<RepositoryState>(state, draft => {
|
||||
draft.currentRepository = undefined;
|
||||
draft.repoNotFound = true;
|
||||
}),
|
||||
},
|
||||
initialState
|
||||
|
|
|
@ -202,7 +202,7 @@ function* handleMainRouteChange(action: Action<Match>) {
|
|||
.split('/')
|
||||
.slice(0, -1)
|
||||
.join('/');
|
||||
yield put(openTreePath(openPath));
|
||||
yield put(openTreePath(openPath || ''));
|
||||
yield put(
|
||||
fetchRepoTree({
|
||||
uri: repoUri,
|
||||
|
|
|
@ -42,6 +42,7 @@ import {
|
|||
fetchRootRepoTree,
|
||||
fetchRootRepoTreeSuccess,
|
||||
fetchRootRepoTreeFailed,
|
||||
dirNotFound,
|
||||
} from '../actions';
|
||||
import { RootState } from '../reducers';
|
||||
import { treeCommitsSelector, createTreeSelector } from '../selectors';
|
||||
|
@ -65,6 +66,9 @@ function* handleFetchRepoTree(action: Action<FetchRepoTreePayload>) {
|
|||
yield call(fetchPath, action.payload!);
|
||||
}
|
||||
} catch (err) {
|
||||
if (action.payload!.isDir && err.body && err.body.statusCode === 404) {
|
||||
yield put(dirNotFound(action.payload!.path));
|
||||
}
|
||||
yield put(fetchRepoTreeFailed(err));
|
||||
}
|
||||
}
|
||||
|
@ -284,8 +288,9 @@ export function* watchFetchBranchesAndCommits() {
|
|||
}
|
||||
|
||||
function* handleRepoRouteChange(action: Action<Match>) {
|
||||
const { url } = action.payload!;
|
||||
yield put(gotoRepo(url));
|
||||
const { repo, org, resource } = action.payload!.params;
|
||||
const uri = `${resource}/${org}/${repo}`;
|
||||
yield put(gotoRepo(uri));
|
||||
}
|
||||
|
||||
export function* watchRepoRouteChange() {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { kfetch } from 'ui/kfetch';
|
||||
|
||||
import { Action } from 'redux-actions';
|
||||
import { call, put, takeEvery, takeLatest } from 'redux-saga/effects';
|
||||
import { call, put, takeEvery, takeLatest, take } from 'redux-saga/effects';
|
||||
import {
|
||||
deleteRepo,
|
||||
deleteRepoFailed,
|
||||
|
@ -27,6 +27,10 @@ import {
|
|||
initRepoCommand,
|
||||
updateDeleteProgress,
|
||||
updateIndexProgress,
|
||||
gotoRepoFailed,
|
||||
loadRepo,
|
||||
loadRepoSuccess,
|
||||
loadRepoFailed,
|
||||
} from '../actions';
|
||||
import { loadLanguageServers } from '../actions/language_server';
|
||||
import { history } from '../utils/url';
|
||||
|
@ -125,13 +129,20 @@ function requestRepoInitCmd(repoUri: string) {
|
|||
});
|
||||
}
|
||||
function* handleGotoRepo(action: Action<string>) {
|
||||
const repoUri = action.payload as string;
|
||||
const repo = yield call(requestRepo, repoUri);
|
||||
history.replace(`${repoUri}/tree/${repo.defaultBranch || 'master'}`);
|
||||
}
|
||||
|
||||
function requestRepo(uri: string) {
|
||||
return kfetch({ pathname: `/api/code/repo${uri}`, method: 'get' });
|
||||
try {
|
||||
const repoUri = action.payload as string;
|
||||
yield put(loadRepo(repoUri));
|
||||
const loadRepoDoneAction = yield take([String(loadRepoSuccess), String(loadRepoFailed)]);
|
||||
if (loadRepoDoneAction.type === String(loadRepoSuccess)) {
|
||||
history.replace(`/${repoUri}/tree/${loadRepoDoneAction.payload.defaultBranch || 'master'}`);
|
||||
} else {
|
||||
// redirect to root project path if repo not found to show 404 page
|
||||
history.replace(`/${action.payload}/tree/master`);
|
||||
}
|
||||
} catch (e) {
|
||||
history.replace(`/${action.payload}/tree/master`);
|
||||
yield put(gotoRepoFailed(e));
|
||||
}
|
||||
}
|
||||
|
||||
export function* watchImportRepo() {
|
||||
|
|
|
@ -294,6 +294,20 @@ export default function exploreRepositoryFunctonalTests({
|
|||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
it('goes to a repository which does not exist should render the 404 error page', async () => {
|
||||
log.debug('it goes to a repository which does not exist');
|
||||
const notExistRepoUri = 'github.com/I_DO_NOT_EXIST/I_DO_NOT_EXIST';
|
||||
const url = `${PageObjects.common.getHostPort()}/app/code#/${notExistRepoUri}`;
|
||||
await browser.get(url);
|
||||
await retry.try(async () => {
|
||||
const currentUrl: string = await browser.getCurrentUrl();
|
||||
expect(currentUrl.indexOf(notExistRepoUri)).to.greaterThan(0);
|
||||
});
|
||||
await retry.try(async () => {
|
||||
expect(await testSubjects.exists('codeNotFoundErrorPage')).ok();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue