mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-07-07 19:23:06 +02:00
Fixed bug causing multiple requests for changesets
Fixed bug related to displaying errors additionally: implemented i18n
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"changeset": {
|
||||
"id": "ID",
|
||||
"description": "Description",
|
||||
"contact": "Contact",
|
||||
"date": "Date",
|
||||
"summary": "Changeset {{id}} committed {{time}}"
|
||||
},
|
||||
"author": {
|
||||
"name": "Author",
|
||||
"mail": "Mail"
|
||||
}
|
||||
}
|
||||
@@ -43,5 +43,19 @@
|
||||
"submit": "Yes",
|
||||
"cancel": "No"
|
||||
}
|
||||
},
|
||||
"changesets": {
|
||||
"changeset": {
|
||||
"id": "ID",
|
||||
"description": "Description",
|
||||
"contact": "Contact",
|
||||
"date": "Date",
|
||||
"summary": "Changeset {{id}} committed {{time}}"
|
||||
},
|
||||
"author": {
|
||||
"name": "Author",
|
||||
"mail": "Mail"
|
||||
},
|
||||
"branchselector-label": "Branch:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export default class ChangesetAuthor extends React.Component<Props> {
|
||||
render() {
|
||||
const { changeset } = this.props;
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{changeset.author.name}{" "}
|
||||
<a
|
||||
className="is-hidden-mobile"
|
||||
@@ -21,7 +21,7 @@ export default class ChangesetAuthor extends React.Component<Props> {
|
||||
{changeset.author.mail}
|
||||
>
|
||||
</a>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { ExtensionPoint } from "@scm-manager/ui-extensions";
|
||||
import type { Changeset } from "@scm-manager/ui-types";
|
||||
import { Image } from "@scm-manager/ui-components";
|
||||
import type { Changeset } from "../../../../../scm-ui-components/packages/ui-types/src/index";
|
||||
import { Image } from "../../../../../scm-ui-components/packages/ui-components/src/index";
|
||||
|
||||
type Props = {
|
||||
changeset: Changeset
|
||||
@@ -12,7 +12,7 @@ class ChangesetAvatar extends React.Component<Props> {
|
||||
render() {
|
||||
const { changeset } = this.props;
|
||||
return (
|
||||
<p className="image is-64x64">
|
||||
<div className="image is-64x64">
|
||||
<ExtensionPoint
|
||||
name="repos.changeset-table.information"
|
||||
renderAll={true}
|
||||
@@ -20,7 +20,7 @@ class ChangesetAvatar extends React.Component<Props> {
|
||||
>
|
||||
<Image src="/images/blib.jpg" alt="Logo" />
|
||||
</ExtensionPoint>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
import ChangesetRow from "./ChangesetRow";
|
||||
import React from "react";
|
||||
import type { Changeset, Repository } from "@scm-manager/ui-types";
|
||||
import type { Changeset, Repository } from "../../../../../scm-ui-components/packages/ui-types/src/index";
|
||||
import classNames from "classnames";
|
||||
|
||||
type Props = {
|
||||
@@ -1,12 +1,15 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import type { Changeset, Repository } from "@scm-manager/ui-types";
|
||||
import type {
|
||||
Changeset,
|
||||
Repository
|
||||
} from "../../../../../scm-ui-components/packages/ui-types/src/index";
|
||||
import classNames from "classnames";
|
||||
import { translate, Interpolate } from "react-i18next";
|
||||
import ChangesetAvatar from "./ChangesetAvatar";
|
||||
import ChangesetId from "./ChangesetId";
|
||||
import injectSheet from "react-jss";
|
||||
import { DateFromNow } from "@scm-manager/ui-components";
|
||||
import { DateFromNow } from "../../../../../scm-ui-components/packages/ui-components/src/index";
|
||||
import ChangesetAuthor from "./ChangesetAuthor";
|
||||
|
||||
const styles = {
|
||||
@@ -38,7 +41,7 @@ class ChangesetRow extends React.Component<Props> {
|
||||
const { changeset, classes } = this.props;
|
||||
const changesetLink = this.createLink(changeset);
|
||||
const dateFromNow = <DateFromNow date={changeset.date} />;
|
||||
const authorLine = <ChangesetAuthor changeset={changeset}/>;
|
||||
const authorLine = <ChangesetAuthor changeset={changeset} />;
|
||||
return (
|
||||
<article className={classNames("media", classes.inner)}>
|
||||
<figure className="media-left">
|
||||
@@ -50,7 +53,7 @@ class ChangesetRow extends React.Component<Props> {
|
||||
{changeset.description}
|
||||
<br />
|
||||
<Interpolate
|
||||
i18nKey="changeset.summary"
|
||||
i18nKey="changesets.changeset.summary"
|
||||
id={changesetLink}
|
||||
time={dateFromNow}
|
||||
/>
|
||||
@@ -63,4 +66,4 @@ class ChangesetRow extends React.Component<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
export default injectSheet(styles)(translate("changesets")(ChangesetRow));
|
||||
export default injectSheet(styles)(translate("repos")(ChangesetRow));
|
||||
@@ -1,10 +1,10 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { translate } from "react-i18next";
|
||||
import {
|
||||
ErrorNotification,
|
||||
Loading,
|
||||
Page,
|
||||
Paginator
|
||||
} from "@scm-manager/ui-components";
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
getBranchNames
|
||||
} from "../../repos/modules/branches";
|
||||
import type { PagedCollection, Repository } from "@scm-manager/ui-types";
|
||||
import ChangesetList from "../components/ChangesetList";
|
||||
import ChangesetList from "../components/changesets/ChangesetList";
|
||||
import DropDown from "../components/DropDown";
|
||||
import { withRouter } from "react-router-dom";
|
||||
|
||||
@@ -38,7 +38,12 @@ type Props = {
|
||||
) => void,
|
||||
list: PagedCollection,
|
||||
fetchChangesetsByLink: string => void,
|
||||
page: number
|
||||
page: number,
|
||||
t: string => string
|
||||
};
|
||||
|
||||
type State = {
|
||||
branch: string
|
||||
};
|
||||
|
||||
class Changesets extends React.PureComponent<State, Props> {
|
||||
@@ -54,6 +59,10 @@ class Changesets extends React.PureComponent<State, Props> {
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.updateContent();
|
||||
}
|
||||
|
||||
updateContent() {
|
||||
const { namespace, name } = this.props.repository;
|
||||
const branchName = this.props.match.params.branch;
|
||||
const {
|
||||
@@ -74,11 +83,16 @@ class Changesets extends React.PureComponent<State, Props> {
|
||||
fetchBranchesByNamespaceAndName(namespace, name);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
componentDidUpdate(prevProps: Props, prevState: State, snapshot: any) {
|
||||
const { page, list, repository, match } = this.props;
|
||||
const { namespace, name } = repository;
|
||||
const branch = match.params.branch;
|
||||
|
||||
if (branch !== prevState.branch) {
|
||||
this.updateContent();
|
||||
this.setState({ branch });
|
||||
}
|
||||
|
||||
if (list && (list.page || list.page === 0)) {
|
||||
// backend starts paging at 0
|
||||
const statePage: number = list.page + 1;
|
||||
@@ -99,13 +113,14 @@ class Changesets extends React.PureComponent<State, Props> {
|
||||
render() {
|
||||
const { changesets, loading, error } = this.props;
|
||||
|
||||
if (error) {
|
||||
return <ErrorNotification error={error} />;
|
||||
}
|
||||
|
||||
if (loading || !changesets) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <ErrorNotification error={error} />;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{this.renderTable()}
|
||||
@@ -116,12 +131,14 @@ class Changesets extends React.PureComponent<State, Props> {
|
||||
|
||||
renderTable = () => {
|
||||
const branch = this.props.match.params.branch;
|
||||
const { repository, changesets, branchNames } = this.props;
|
||||
const { repository, changesets, branchNames, t } = this.props;
|
||||
|
||||
if (branchNames && branchNames.length > 0) {
|
||||
return (
|
||||
<div>
|
||||
<label className="label">Branch: </label>
|
||||
<label className="label">
|
||||
{t("changesets.branchselector-label")}
|
||||
</label>
|
||||
<DropDown
|
||||
options={branchNames}
|
||||
preselectedOption={branch}
|
||||
@@ -145,9 +162,13 @@ class Changesets extends React.PureComponent<State, Props> {
|
||||
|
||||
branchChanged = (branchName: string): void => {
|
||||
const { history, repository } = this.props;
|
||||
history.push(
|
||||
`/repo/${repository.namespace}/${repository.name}/${branchName}/history`
|
||||
);
|
||||
if (branchName === undefined || branchName === "") {
|
||||
history.push(`/repo/${repository.namespace}/${repository.name}/history`);
|
||||
} else {
|
||||
history.push(
|
||||
`/repo/${repository.namespace}/${repository.name}/${branchName}/history`
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -225,5 +246,5 @@ export default withRouter(
|
||||
connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(Changesets)
|
||||
)(translate("repos")(Changesets))
|
||||
);
|
||||
|
||||
@@ -105,22 +105,22 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
<Route
|
||||
exact
|
||||
path={`${url}/history`}
|
||||
component={() => <Changesets repository={repository} />}
|
||||
render={() => <Changesets repository={repository} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${url}/history/:page`}
|
||||
component={() => <Changesets repository={repository} />}
|
||||
render={() => <Changesets repository={repository} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${url}/:branch/history`}
|
||||
component={() => <Changesets repository={repository} />}
|
||||
render={() => <Changesets repository={repository} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${url}/:branch/history/:page`}
|
||||
component={() => <Changesets repository={repository} />}
|
||||
render={() => <Changesets repository={repository} />}
|
||||
/>
|
||||
</div>
|
||||
<div className="column">
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import {FAILURE_SUFFIX, PENDING_SUFFIX, SUCCESS_SUFFIX} from "../../modules/types";
|
||||
import {apiClient} from "@scm-manager/ui-components";
|
||||
// @flow
|
||||
import {
|
||||
FAILURE_SUFFIX,
|
||||
PENDING_SUFFIX,
|
||||
SUCCESS_SUFFIX
|
||||
} from "../../modules/types";
|
||||
import { apiClient } from "@scm-manager/ui-components";
|
||||
|
||||
export const FETCH_BRANCHES = "scm/repos/FETCH_BRANCHES";
|
||||
export const FETCH_BRANCHES_PENDING = `${FETCH_BRANCHES}_${PENDING_SUFFIX}`;
|
||||
@@ -9,64 +14,81 @@ export const FETCH_BRANCHES_FAILURE = `${FETCH_BRANCHES}_${FAILURE_SUFFIX}`;
|
||||
const REPO_URL = "repositories";
|
||||
|
||||
// Fetching branches
|
||||
export function fetchBranchesByNamespaceAndName(namespace: string, name: string) {
|
||||
return function (dispatch: any) {
|
||||
export function fetchBranchesByNamespaceAndName(
|
||||
namespace: string,
|
||||
name: string
|
||||
) {
|
||||
return function(dispatch: any) {
|
||||
dispatch(fetchBranchesPending(namespace, name));
|
||||
return apiClient.get(REPO_URL + "/" + namespace + "/" + name + "/branches")
|
||||
return apiClient
|
||||
.get(REPO_URL + "/" + namespace + "/" + name + "/branches")
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
dispatch(fetchBranchesSuccess(data, namespace, name))
|
||||
dispatch(fetchBranchesSuccess(data, namespace, name));
|
||||
})
|
||||
.catch(cause => {
|
||||
dispatch(fetchBranchesFailure(namespace, name, cause))
|
||||
})
|
||||
}
|
||||
.catch(error => {
|
||||
dispatch(fetchBranchesFailure(namespace, name, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Action creators
|
||||
export function fetchBranchesPending(namespace: string, name: string) {
|
||||
return {
|
||||
type: FETCH_BRANCHES_PENDING,
|
||||
payload: {namespace, name},
|
||||
payload: { namespace, name },
|
||||
itemId: namespace + "/" + name
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchBranchesSuccess(data: string, namespace: string, name: string) {
|
||||
export function fetchBranchesSuccess(
|
||||
data: string,
|
||||
namespace: string,
|
||||
name: string
|
||||
) {
|
||||
return {
|
||||
type: FETCH_BRANCHES_SUCCESS,
|
||||
payload: {data, namespace, name},
|
||||
payload: { data, namespace, name },
|
||||
itemId: namespace + "/" + name
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchBranchesFailure(namespace: string, name: string, error: Error) {
|
||||
export function fetchBranchesFailure(
|
||||
namespace: string,
|
||||
name: string,
|
||||
error: Error
|
||||
) {
|
||||
return {
|
||||
type: FETCH_BRANCHES_FAILURE,
|
||||
payload: {error, namespace, name},
|
||||
payload: { error, namespace, name },
|
||||
itemId: namespace + "/" + name
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Reducers
|
||||
|
||||
export default function reducer(state: Object = {}, action: Action = {type: "UNKNOWN"}): Object {
|
||||
export default function reducer(
|
||||
state: Object = {},
|
||||
action: Action = { type: "UNKNOWN" }
|
||||
): Object {
|
||||
switch (action.type) {
|
||||
case FETCH_BRANCHES_SUCCESS:
|
||||
const key = action.payload.namespace + "/" + action.payload.name;
|
||||
let oldBranchesByNames = {[key]: {}};
|
||||
let oldBranchesByNames = { [key]: {} };
|
||||
if (state[key] !== undefined) {
|
||||
oldBranchesByNames[key] = state[key]
|
||||
oldBranchesByNames[key] = state[key];
|
||||
}
|
||||
return {
|
||||
[key]: {
|
||||
byNames: extractBranchesByNames(action.payload.data, oldBranchesByNames[key].byNames)
|
||||
byNames: extractBranchesByNames(
|
||||
action.payload.data,
|
||||
oldBranchesByNames[key].byNames
|
||||
)
|
||||
}
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function extractBranchesByNames(data: any, oldBranchesByNames: any): Branch[] {
|
||||
@@ -78,14 +100,18 @@ function extractBranchesByNames(data: any, oldBranchesByNames: any): Branch[] {
|
||||
}
|
||||
|
||||
for (let name in oldBranchesByNames) {
|
||||
branchesByNames[name] = oldBranchesByNames[name]
|
||||
branchesByNames[name] = oldBranchesByNames[name];
|
||||
}
|
||||
return branchesByNames;
|
||||
}
|
||||
|
||||
// Selectors
|
||||
|
||||
export function getBranchesForNamespaceAndNameFromState(namespace: string, name: string, state: Object) {
|
||||
export function getBranchesForNamespaceAndNameFromState(
|
||||
namespace: string,
|
||||
name: string,
|
||||
state: Object
|
||||
) {
|
||||
const key = namespace + "/" + name;
|
||||
if (!state.branches[key]) {
|
||||
return null;
|
||||
|
||||
@@ -140,8 +140,8 @@ function fetchChangesetsFailure(
|
||||
payload: {
|
||||
namespace,
|
||||
name,
|
||||
branch,
|
||||
error
|
||||
error,
|
||||
branch
|
||||
},
|
||||
itemId: createItemId(namespace, name, branch)
|
||||
};
|
||||
|
||||
@@ -127,7 +127,7 @@ describe("changesets", () => {
|
||||
});
|
||||
|
||||
it("should fetch changesets by page", () => {
|
||||
fetchMock.getOnce(DEFAULT_BRANCH_URL + "?page=5", "{}");
|
||||
fetchMock.getOnce(DEFAULT_BRANCH_URL + "?page=4", "{}");
|
||||
|
||||
const expectedActions = [
|
||||
{
|
||||
@@ -149,7 +149,7 @@ describe("changesets", () => {
|
||||
});
|
||||
|
||||
it("should fetch changesets by branch and page", () => {
|
||||
fetchMock.getOnce(SPECIFIC_BRANCH_URL + "?page=5", "{}");
|
||||
fetchMock.getOnce(SPECIFIC_BRANCH_URL + "?page=4", "{}");
|
||||
|
||||
const expectedActions = [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user