fixed branch selection urls and styles branch selector

This commit is contained in:
Sebastian Sdorra
2018-10-17 11:33:40 +02:00
parent e841c06934
commit e6c16c3fc5
7 changed files with 92 additions and 208 deletions

View File

@@ -3,16 +3,16 @@ import React from "react";
import {translate} from "react-i18next";
import type {PagedCollection} from "@scm-manager/ui-types";
import {Button} from "./buttons";
import {withRouter} from "react-router-dom";
type Props = {
collection: PagedCollection,
t: string => string,
match: any
page: number,
// context props
t: string => string
};
class LinkPaginator extends React.Component<Props> {
//TODO: HATEOAS-Links verwenden
renderFirstButton() {
return (
@@ -26,30 +26,32 @@ class LinkPaginator extends React.Component<Props> {
}
renderPreviousButton(label?: string) {
const { match } = this.props;
const page = parseInt(match.params.page) || 1;
const { page } = this.props;
const previousPage = page - 1;
return (
<Button
className={"pagination-previous"}
label={label ? label : previousPage.toString()}
disabled={previousPage < 1}
disabled={!this.hasLink("prev")}
link={`${previousPage}`}
/>
);
}
renderNextButton(label?: string) {
const { match, collection } = this.props;
let page = parseInt(match.params.page) || 1;
hasLink(name: string) {
const { collection } = this.props;
return collection._links[name];
}
renderNextButton(label?: string) {
const { page } = this.props;
const nextPage = page + 1;
return (
<Button
className={"pagination-next"}
label={label ? label : nextPage.toString()}
disabled={nextPage >= collection.pageTotal + 1}
disabled={!this.hasLink("next")}
link={`${nextPage}`}
/>
);
@@ -128,4 +130,4 @@ class LinkPaginator extends React.Component<Props> {
}
}
export default withRouter(translate("commons")(LinkPaginator));
export default translate("commons")(LinkPaginator);

View File

@@ -59,6 +59,9 @@
"mail": "Mail"
}
},
"branch-selector": {
"label": "Branches"
},
"branch-chooser": {
"error-title": "Error",
"error-subtitle": "Could not fetch branches"

View File

@@ -1,18 +1,20 @@
// @flow
import React from "react";
import classNames from "classnames";
type Props = {
options: string[],
optionSelected: string => void,
preselectedOption?: string
preselectedOption?: string,
className: any
};
class DropDown extends React.Component<Props> {
render() {
const { options, preselectedOption } = this.props;
const { options, preselectedOption, className } = this.props;
return (
<div className="select">
<div className={classNames(className, "select")}>
<select
value={preselectedOption ? preselectedOption : ""}
onChange={this.change}

View File

@@ -1,166 +0,0 @@
// @flow
import * as React from "react";
import type { Branch, Repository } from "@scm-manager/ui-types";
import { connect } from "react-redux";
import {
fetchBranches,
getBranches,
getFetchBranchesFailure,
isFetchBranchesPending
} from "../modules/branches";
import DropDown from "../components/DropDown";
import type { History } from "history";
import { ErrorPage, Loading } from "@scm-manager/ui-components";
import { translate } from "react-i18next";
type Props = {
repository: Repository,
label: string, //TODO: Should this be here?
onChange: string => void,
children: React.Node,
selected?: string,
// State props
branches: Branch[],
error: Error,
loading: boolean,
// Dispatch props
fetchBranches: Repository => void,
// Context props
t: string => string
};
type State = {
selectedBranch?: Branch
};
class BranchChooser extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {};
}
componentDidMount() {
this.props.fetchBranches(this.props.repository);
}
render() {
const { loading, error, t, repository } = this.props;
if (error) {
return (
<ErrorPage
title={t("branch-chooser.error-title")}
subtitle={t("branch-chooser.error-subtitle")}
error={error}
/>
);
}
if (!repository) {
return null;
}
if (loading) {
return <Loading />;
}
const { selectedBranch } = this.state;
const childrenWithBranch = React.Children.map(
this.props.children,
child => {
return React.cloneElement(child, {
branch: selectedBranch
});
}
);
return (
<>
{this.renderBranchChooser()}
{childrenWithBranch}
</>
);
}
renderBranchChooser() {
const { label, branches, selected } = this.props;
if (!branches || branches.length === 0) {
return null;
}
return (
<div className={"box"}>
<label className="label">{label}</label>
<DropDown
options={branches.map(b => b.name)}
preselectedOption={
this.state.selectedBranch
? this.state.selectedBranch.name
: selected
}
optionSelected={(branchName: string) => {
this.branchSelected(branchName, true);
}}
/>
</div>
);
}
branchSelected = (branch: string, changed: boolean) => {
for (let b of this.props.branches) {
if (b.name === branch) {
this.updateBranch(branch, b, changed);
break;
}
}
};
updateBranch = (branchName: string, branch: Branch, changed: boolean) => {
this.setState(
prevState => {
if (
!prevState.selectedBranch ||
branchName !== prevState.selectedBranch.name
) {
return { selectedBranch: branch };
}
},
() => {
if (changed) {
this.props.onChange(branch.name);
}
}
);
};
}
const mapDispatchToProps = dispatch => {
return {
fetchBranches: (repo: Repository) => {
dispatch(fetchBranches(repo));
}
};
};
const mapStateToProps = (state: any, ownProps: Props) => {
const { repository } = ownProps;
const loading = isFetchBranchesPending(state, repository);
const error = getFetchBranchesFailure(state, repository);
const branches = getBranches(state, repository);
return {
loading,
error,
branches
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(translate("repos")(BranchChooser));

View File

@@ -19,6 +19,8 @@ type Props = {
repository: Repository,
baseUrl: string,
selected: string,
baseUrlWithBranch: string,
baseUrlWithoutBranch: string,
// State props
branches: Branch[],
@@ -49,15 +51,16 @@ class BranchRoot extends React.Component<Props> {
return url;
};
matchedUrl = () => {
return this.stripEndingSlash(this.props.baseUrl);
};
branchSelected = (branch: Branch) => {
const url = this.matchedUrl();
this.props.history.push(
`${url}/${encodeURIComponent(branch.name)}/changesets/`
);
branchSelected = (branch?: Branch) => {
let url;
if (branch) {
url = `${this.props.baseUrlWithBranch}/${encodeURIComponent(
branch.name
)}/changesets/`;
} else {
url = `${this.props.baseUrlWithoutBranch}/`;
}
this.props.history.push(url);
};
findSelectedBranch = () => {

View File

@@ -3,10 +3,24 @@
import React from "react";
import type { Branch } from "@scm-manager/ui-types";
import DropDown from "../components/DropDown";
import { translate } from "react-i18next";
import injectSheet from "react-jss";
import { compose } from "redux";
import classNames from "classnames";
const styles = {
zeroflex: {
flexGrow: 0
}
};
type Props = {
branches: Branch[], // TODO: Use generics?
selected?: Branch => void
selected?: Branch => void,
// context props
classes: Object,
t: string => string
};
type State = { selectedBranch?: Branch };
@@ -18,19 +32,33 @@ class BranchSelector extends React.Component<Props, State> {
}
render() {
const { branches } = this.props;
const { branches, classes, t } = this.props;
if (branches) {
return (
<>
<DropDown
options={branches.map(b => b.name)}
optionSelected={this.branchSelected}
preselectedOption={
this.state.selectedBranch ? this.state.selectedBranch.name : ""
}
/>
</>
<div className="box field is-horizontal">
<div
className={classNames("field-label", "is-normal", classes.zeroflex)}
>
<label className="label">{t("branch-selector.label")}</label>
</div>
<div className="field-body">
<div className="field is-narrow">
<div className="control">
<DropDown
className="is-fullwidth"
options={branches.map(b => b.name)}
optionSelected={this.branchSelected}
preselectedOption={
this.state.selectedBranch
? this.state.selectedBranch.name
: ""
}
/>
</div>
</div>
</div>
</div>
);
}
}
@@ -39,11 +67,12 @@ class BranchSelector extends React.Component<Props, State> {
const { branches, selected } = this.props;
const branch = branches.find(b => b.name === branchName);
if (branch) {
selected(branch);
this.setState({ selectedBranch: branch });
}
selected(branch);
this.setState({ selectedBranch: branch });
};
}
export default BranchSelector;
export default compose(
injectSheet(styles),
translate("repos")
)(BranchSelector);

View File

@@ -111,12 +111,23 @@ class RepositoryRoot extends React.Component<Props> {
path={`${url}/edit`}
component={() => <Edit repository={repository} />}
/>
<Route
path={`${url}/changesets`}
render={() => (
<BranchRoot
repository={repository}
baseUrlWithBranch={`${url}/branches`}
baseUrlWithoutBranch={`${url}/changesets`}
/>
)}
/>
<Route
path={`${url}/branches/:branch/changesets`}
render={() => (
<BranchRoot
repository={repository}
baseUrl={`${url}/branches`}
baseUrlWithBranch={`${url}/branches`}
baseUrlWithoutBranch={`${url}/changesets`}
/>
)}
/>
@@ -128,7 +139,7 @@ class RepositoryRoot extends React.Component<Props> {
<NavLink to={url} label={t("repository-root.information")} />
<NavLink
activeOnlyWhenExact={false}
to={`${url}/branches/master/changesets/1`}
to={`${url}/changesets/`}
label={t("repository-root.history")}
activeWhenMatch={this.matches}
/>