Bootstrapped reimplementation of Changeset list

This commit is contained in:
Philipp Czora
2018-10-09 21:36:41 +02:00
parent f95ffe25f3
commit 62abae4368
4 changed files with 196 additions and 37 deletions

View File

@@ -0,0 +1,106 @@
// @flow
import React from "react";
import type {Branch, Repository} from "@scm-manager/ui-types";
import {connect} from "react-redux";
import {fetchBranches, getBranch, getBranchNames, isFetchBranchesPending} from "../modules/branches";
import DropDown from "../components/DropDown";
import type {History} from "history";
import {withRouter} from "react-router-dom";
import ChangesetContainer from "./ChangesetContainer";
import {Loading} from "@scm-manager/ui-components";
type Props = {
repository: Repository,
branches: Branch[],
branchNames: string[],
fetchBranches: Repository => void,
history: History,
match: any,
selectedBranch: Branch,
label: string, //TODO: Should this be here?
loading: boolean
};
type State = {};
class BranchChangesets extends React.Component<Props, State> {
componentDidMount() {
this.props.fetchBranches(this.props.repository);
}
render() {
const {
repository,
branchNames,
match,
selectedBranch,
label,
loading
} = this.props;
const selectedBranchName = match.params.branch;
if (loading) {
return <Loading />;
}
// TODO: Handle errors
if (!branchNames || branchNames.length === 0) {
return null;
}
return (
<>
<div className={"box"}>
<label className="label">{label}</label>
<DropDown
options={branchNames}
preselectedOption={selectedBranchName}
optionSelected={branch => this.branchSelected(branch)}
/>
</div>
<ChangesetContainer repository={repository} branch={selectedBranch} />
</>
);
}
//TODO: Maybe extract this and let it be passed from parent component
branchSelected = (branchName: string) => {
const { namespace, name } = this.props.repository;
if (branchName === "") {
this.props.history.push(`/repo/${namespace}/${name}/changesets`);
} else {
this.props.history.push(
`/repo/${namespace}/${name}/branches/${branchName}/changesets`
);
}
};
}
const mapDispatchToProps = dispatch => {
return {
fetchBranches: (repo: Repository) => {
dispatch(fetchBranches(repo));
}
};
};
const mapStateToProps = (state: any, ownProps: Props) => {
const loading = isFetchBranchesPending(state, ownProps.repository);
const branchNames = getBranchNames(state, ownProps.repository);
const selectedBranch = getBranch(
state,
ownProps.repository,
ownProps.match.params.branch //TODO: Maybe let parent component pass selected branch
);
return {
loading,
branchNames,
selectedBranch
};
};
export default withRouter(
connect(
mapStateToProps,
mapDispatchToProps
)(BranchChangesets)
);

View File

@@ -0,0 +1,61 @@
// @flow
import React from "react";
import { withRouter } from "react-router-dom";
import type { Branch, Changeset, Repository } from "@scm-manager/ui-types";
import {
fetchChangesetsByBranch,
getChangesets,
isFetchChangesetsPending
} from "../modules/changesets";
import { connect } from "react-redux";
import ChangesetList from "../components/changesets/ChangesetList";
import { Loading } from "@scm-manager/ui-components";
type Props = {
fetchChangesetsByBranch: (Repository, Branch) => void,
repository: Repository, //TODO: Do we really need/want this here?
branch: Branch,
changesets: Changeset[],
loading: boolean
};
type State = {};
class ChangesetContainer extends React.Component<Props, State> {
componentDidMount() {
const { fetchChangesetsByBranch, repository, branch } = this.props;
fetchChangesetsByBranch(repository, branch); //TODO: fetch by page
}
render() {
const { repository, changesets, loading } = this.props;
if (loading) {
return <Loading />;
}
if (!changesets || changesets.length === 0) {
return null;
}
return <ChangesetList repository={repository} changesets={changesets} />;
}
}
const mapDispatchToProps = dispatch => {
return {
fetchChangesetsByBranch: (repo: Repository, branch: Branch) => {
dispatch(fetchChangesetsByBranch(repo, branch));
}
};
};
const mapStateToProps = (state: any, ownProps: Props) => {
const { repository, branch } = ownProps;
const changesets = getChangesets(state, repository, branch);
const loading = isFetchChangesetsPending(state, repository, branch);
return { changesets, loading };
};
export default withRouter(
connect(
mapStateToProps,
mapDispatchToProps
)(ChangesetContainer)
);

View File

@@ -1,31 +1,18 @@
//@flow
import React from "react";
import {
deleteRepo,
fetchRepo,
getFetchRepoFailure,
getRepository,
isFetchRepoPending
} from "../modules/repos";
import { connect } from "react-redux";
import { Route } from "react-router-dom";
import type { Repository } from "@scm-manager/ui-types";
import {
Page,
Loading,
ErrorPage,
Navigation,
NavLink,
Section
} from "@scm-manager/ui-components";
import { translate } from "react-i18next";
import {deleteRepo, fetchRepo, getFetchRepoFailure, getRepository, isFetchRepoPending} from "../modules/repos";
import {connect} from "react-redux";
import {Route} from "react-router-dom";
import type {Repository} from "@scm-manager/ui-types";
import {ErrorPage, Loading, Navigation, NavLink, Page, Section} from "@scm-manager/ui-components";
import {translate} from "react-i18next";
import RepositoryDetails from "../components/RepositoryDetails";
import DeleteNavAction from "../components/DeleteNavAction";
import Edit from "../containers/Edit";
import type { History } from "history";
import type {History} from "history";
import EditNavLink from "../components/EditNavLink";
import Changesets from "./Changesets";
import BranchChangesets from "./BranchChangesets";
type Props = {
namespace: string,
@@ -94,7 +81,7 @@ class RepositoryRoot extends React.Component<Props> {
}
const url = this.matchedUrl();
// TODO: Changesets need to be adjusted (i.e. sub-routes need to be handled in sub-components)
return (
<Page title={repository.namespace + "/" + repository.name}>
<div className="columns">
@@ -108,25 +95,34 @@ class RepositoryRoot extends React.Component<Props> {
path={`${url}/edit`}
component={() => <Edit repository={repository} />}
/>
<Route
exact
path={`${url}/changesets`}
render={() => <Changesets repository={repository} />}
render={() => (
<BranchChangesets repository={repository} label={"Branches"} />
)}
/>
<Route
exact
path={`${url}/changesets/:page`}
render={() => <Changesets repository={repository} />}
render={() => (
<BranchChangesets repository={repository} label={"Branches"} />
)}
/>
<Route
exact
path={`${url}/:branch/changesets`}
render={() => <Changesets repository={repository} />}
path={`${url}/branches/:branch/changesets`}
render={() => (
<BranchChangesets repository={repository} label={"Branches"} />
)}
/>
<Route
exact
path={`${url}/:branch/changesets/:page`}
render={() => <Changesets repository={repository} />}
path={`${url}/branches/:branch/changesets/:page`}
render={() => (
<BranchChangesets repository={repository} label={"Branches"} />
)}
/>
</div>
<div className="column">

View File

@@ -1,12 +1,8 @@
// @flow
import {
FAILURE_SUFFIX,
PENDING_SUFFIX,
SUCCESS_SUFFIX
} from "../../modules/types";
import { apiClient } from "@scm-manager/ui-components";
import type { Repository, Action, Branch } from "@scm-manager/ui-types";
import { isPending } from "../../modules/pending";
import {FAILURE_SUFFIX, PENDING_SUFFIX, SUCCESS_SUFFIX} from "../../modules/types";
import {apiClient} from "@scm-manager/ui-components";
import type {Action, Branch, Repository} from "@scm-manager/ui-types";
import {isPending} from "../../modules/pending";
export const FETCH_BRANCHES = "scm/repos/FETCH_BRANCHES";
export const FETCH_BRANCHES_PENDING = `${FETCH_BRANCHES}_${PENDING_SUFFIX}`;
@@ -113,7 +109,7 @@ export function getBranchNames(
repository: Repository
): ?Array<Branch> {
const key = createKey(repository);
if (!state.branches[key] || !state.branches[key].byNames) {
if (!state.branches || !state.branches[key] || !state.branches[key].byNames) {
return [];
}
return Object.keys(state.branches[key].byNames);