Added pending/error-logic for changesets

Styled the changeset table a bit
This commit is contained in:
Philipp Czora
2018-09-12 17:15:58 +02:00
parent ee87ada415
commit 75002ffcff
4 changed files with 91 additions and 19 deletions

View File

@@ -1,5 +1,6 @@
import React from "react" import React from "react"
import type { Changeset } from "@scm-manager/ui-types" import type { Changeset } from "@scm-manager/ui-types"
import {ExtensionPoint} from "@scm-manager/ui-extensions";
type Props = { type Props = {
changeset: Changeset changeset: Changeset
@@ -7,13 +8,19 @@ type Props = {
class ChangesetRow extends React.Component<Props> { class ChangesetRow extends React.Component<Props> {
// Todo: Add extension point to author field
render() { render() {
const { changeset } = this.props; const { changeset } = this.props;
// todo: i18n
return <tr> return <tr>
<td>{ changeset.author.name }</td> <td>
<td>{ changeset.description }</td> <ExtensionPoint
<td>{ changeset.date }</td> name="repos.changeset-table.information"
renderAll={true}
props={{ changeset }}
/>
<p>{changeset.description}</p>
<p className="is-size-7">Changeset { changeset.id } commited at { changeset.date }</p>
<p className="is-size-7">{changeset.author.name} <a href={"mailto:" + changeset.author.mail}>&lt;{changeset.author.mail}&gt;</a></p></td>
</tr> </tr>
} }
} }

View File

@@ -22,13 +22,9 @@ class Changesets extends React.Component<Props> {
if (!changesets) { if (!changesets) {
return null; return null;
} }
return <table className="table is-hoverable is-fullwidth"> return <table className="table is-hoverable is-fullwidth is-striped is-bordered">
<thead> <thead>
<tr> <tr>Changesets</tr>
<th>{t("author.name")}</th>
<th>{t("changeset.description")}</th>
<th className="is-hidden-mobile">{t("changeset.date")}</th>
</tr>
</thead> </thead>
<tbody> <tbody>
{changesets.map((changeset, index) => { {changesets.map((changeset, index) => {

View File

@@ -2,6 +2,8 @@
import {FAILURE_SUFFIX, PENDING_SUFFIX, SUCCESS_SUFFIX} from "../../modules/types"; import {FAILURE_SUFFIX, PENDING_SUFFIX, SUCCESS_SUFFIX} from "../../modules/types";
import {apiClient} from "@scm-manager/ui-components"; import {apiClient} from "@scm-manager/ui-components";
import {isPending} from "../../modules/pending";
import {getFailure} from "../../modules/failure";
export const FETCH_CHANGESETS = "scm/repos/FETCH_CHANGESETS"; export const FETCH_CHANGESETS = "scm/repos/FETCH_CHANGESETS";
export const FETCH_CHANGESETS_PENDING = `${FETCH_CHANGESETS}_${PENDING_SUFFIX}`; export const FETCH_CHANGESETS_PENDING = `${FETCH_CHANGESETS}_${PENDING_SUFFIX}`;
@@ -19,7 +21,7 @@ export function fetchChangesetsByNamespaceAndName(namespace: string, name: strin
.then(data => { .then(data => {
dispatch(fetchChangesetsSuccess(data, namespace, name)) dispatch(fetchChangesetsSuccess(data, namespace, name))
}).catch(cause => { }).catch(cause => {
dispatch(fetchChangesetsFailure(link, cause)) dispatch(fetchChangesetsFailure(namespace, name, cause))
}) })
} }
} }
@@ -30,14 +32,16 @@ export function fetchChangesetsPending(namespace: string, name: string): Action
payload: { payload: {
namespace, namespace,
name name
} },
itemId: namespace + "/" + name
} }
} }
export function fetchChangesetsSuccess(collection: any, namespace: string, name: string): Action { export function fetchChangesetsSuccess(collection: any, namespace: string, name: string): Action {
return { return {
type: FETCH_CHANGESETS_SUCCESS, type: FETCH_CHANGESETS_SUCCESS,
payload: {collection, namespace, name} payload: {collection, namespace, name},
itemId: namespace + "/" + name
} }
} }
@@ -48,7 +52,8 @@ function fetchChangesetsFailure(namespace: string, name: string, error: Error):
namespace, namespace,
name, name,
error error
} },
itemId: namespace + "/" + name
} }
} }
@@ -85,10 +90,19 @@ function extractChangesetsByIds(data: any, oldChangesetsByIds: any) {
} }
//selectors //selectors
export function getChangesetsForNameAndNamespaceFromState(namespace: string, name: string, state: any) { export function getChangesetsForNameAndNamespaceFromState(namespace: string, name: string, state: Object) {
const key = namespace + "/" + name; const key = namespace + "/" + name;
if (!state.changesets[key]) { if (!state.changesets[key]) {
return null; return null;
} }
return Object.values(state.changesets[key].byId); return Object.values(state.changesets[key].byId);
} }
export function isFetchChangesetsPending( state: Object, namespace: string, name: string) {
return isPending(state, FETCH_CHANGESETS, namespace + "/" + name)
}
export function getFetchChangesetsFailure( state: Object, namespace: string, name: string) {
return getFailure(state, FETCH_CHANGESETS, namespace + "/" + name);
}

View File

@@ -4,10 +4,11 @@ import configureMockStore from "redux-mock-store";
import thunk from "redux-thunk"; import thunk from "redux-thunk";
import fetchMock from "fetch-mock"; import fetchMock from "fetch-mock";
import { import {
FETCH_CHANGESETS, FETCH_CHANGESETS_FAILURE,
FETCH_CHANGESETS_PENDING, FETCH_CHANGESETS_PENDING,
FETCH_CHANGESETS_SUCCESS, FETCH_CHANGESETS_SUCCESS,
fetchChangesetsByNamespaceAndName, fetchChangesetsByNamespaceAndName,
fetchChangesetsSuccess, getChangesetsForNameAndNamespaceFromState fetchChangesetsSuccess, getChangesetsForNameAndNamespaceFromState, getFetchChangesetsFailure, isFetchChangesetsPending
} from "./changesets"; } from "./changesets";
import reducer from "./changesets"; import reducer from "./changesets";
@@ -26,10 +27,12 @@ describe("fetching of changesets", () => {
fetchMock.getOnce(URL, "{}"); fetchMock.getOnce(URL, "{}");
const expectedActions = [ const expectedActions = [
{type: FETCH_CHANGESETS_PENDING, payload: {namespace: "foo", name: "bar"}}, {type: FETCH_CHANGESETS_PENDING, payload: {namespace: "foo", name: "bar"},
itemId: "foo/bar"},
{ {
type: FETCH_CHANGESETS_SUCCESS, type: FETCH_CHANGESETS_SUCCESS,
payload: {collection, namespace: "foo", name: "bar"} payload: {collection, namespace: "foo", name: "bar"},
itemId: "foo/bar"
} }
]; ];
@@ -37,6 +40,27 @@ describe("fetching of changesets", () => {
return store.dispatch(fetchChangesetsByNamespaceAndName("foo", "bar")).then(() => { return store.dispatch(fetchChangesetsByNamespaceAndName("foo", "bar")).then(() => {
expect(store.getActions()).toEqual(expectedActions); expect(store.getActions()).toEqual(expectedActions);
}); });
});
it("should fail fetching changesets on error", () => {
fetchMock.getOnce(URL, 500);
const expectedActions = [
{type: FETCH_CHANGESETS_PENDING, payload: {namespace: "foo", name: "bar"},
itemId: "foo/bar"},
{
type: FETCH_CHANGESETS_SUCCESS,
payload: {collection, namespace: "foo", name: "bar"},
itemId: "foo/bar"
}
];
const store = mockStore({});
return store.dispatch(fetchChangesetsByNamespaceAndName("foo", "bar")).then(() => {
expect(store.getActions()[0]).toEqual(expectedActions[0]);
expect(store.getActions()[1].type).toEqual(FETCH_CHANGESETS_FAILURE);
expect(store.getActions()[1].payload).toBeDefined();
});
}) })
}); });
@@ -93,6 +117,8 @@ describe("changesets reducer", () => {
}); });
describe("changeset selectors", () => { describe("changeset selectors", () => {
const error = new Error("Something went wrong");
it("should get all changesets for a given namespace and name", () => { it("should get all changesets for a given namespace and name", () => {
const state = { const state = {
changesets: { changesets: {
@@ -106,5 +132,34 @@ describe("changeset selectors", () => {
}; };
const result = getChangesetsForNameAndNamespaceFromState("foo", "bar", state); const result = getChangesetsForNameAndNamespaceFromState("foo", "bar", state);
expect(result).toContainEqual({id: "id1"}) expect(result).toContainEqual({id: "id1"})
}) });
it("should return true, when fetching changesets is pending", () => {
const state = {
pending: {
[FETCH_CHANGESETS + "/foo/bar"]: true
}
};
expect(isFetchChangesetsPending(state, "foo", "bar")).toBeTruthy();
});
it("should return false, when fetching changesets is not pending", () => {
expect(isFetchChangesetsPending({}, "foo", "bar")).toEqual(false);
});
it("should return error if fetching changesets failed", () => {
const state = {
failure: {
[FETCH_CHANGESETS + "/foo/bar"]: error
}
};
expect(getFetchChangesetsFailure(state, "foo", "bar")).toEqual(error);
});
it("should return false if fetching changesets did not fail", () => {
expect(getFetchChangesetsFailure({}, "foo", "bar")).toBeUndefined();
})
}); });