diff --git a/scm-ui/public/locales/en/changesets.json b/scm-ui/public/locales/en/changesets.json index 8c804d8f62..b3e996e094 100644 --- a/scm-ui/public/locales/en/changesets.json +++ b/scm-ui/public/locales/en/changesets.json @@ -4,7 +4,7 @@ "description": "Description", "contact": "Contact", "date": "Date", - "summary": "Changeset {{id}} committed at {{time}}" + "summary": "Changeset {{id}} committed {{time}}" }, "author": { "name": "Author", diff --git a/scm-ui/src/repos/components/ChangesetAuthor.js b/scm-ui/src/repos/components/ChangesetAuthor.js new file mode 100644 index 0000000000..d2993daed4 --- /dev/null +++ b/scm-ui/src/repos/components/ChangesetAuthor.js @@ -0,0 +1,27 @@ +//@flow + +import React from "react"; +import type { Changeset } from "@scm-manager/ui-types"; + +type Props = { + changeset: Changeset +}; + +export default class ChangesetAuthor extends React.Component { + render() { + const { changeset } = this.props; + return ( + <> + {changeset.author.name}{" "} + + < + {changeset.author.mail} + > + + + ); + } +} diff --git a/scm-ui/src/repos/components/ChangesetId.js b/scm-ui/src/repos/components/ChangesetId.js new file mode 100644 index 0000000000..7669cd606e --- /dev/null +++ b/scm-ui/src/repos/components/ChangesetId.js @@ -0,0 +1,25 @@ +//@flow + +import { Link } from "react-router-dom"; +import React from "react"; +import type { Repository, Changeset } from "@scm-manager/ui-types"; + +type Props = { + repository: Repository, + changeset: Changeset +}; + +export default class ChangesetId extends React.Component { + render() { + const { repository, changeset } = this.props; + return ( + + {changeset.id.substr(0, 7)} + + ); + } +} diff --git a/scm-ui/src/repos/components/ChangesetList.js b/scm-ui/src/repos/components/ChangesetList.js new file mode 100644 index 0000000000..b5613b3754 --- /dev/null +++ b/scm-ui/src/repos/components/ChangesetList.js @@ -0,0 +1,22 @@ +// @flow +import ChangesetRow from "./ChangesetRow"; +import React from "react"; +import type { Changeset, Repository } from "@scm-manager/ui-types"; +import classNames from "classnames"; + +type Props = { + repository: Repository, + changesets: Changeset[] +}; + +class ChangesetList extends React.Component { + render() { + const { repository, changesets } = this.props; + const content = changesets.map((changeset, index) => { + return ; + }); + return
{content}
; + } +} + +export default ChangesetList; diff --git a/scm-ui/src/repos/components/ChangesetRow.js b/scm-ui/src/repos/components/ChangesetRow.js index cb8691206a..9ec3a7af58 100644 --- a/scm-ui/src/repos/components/ChangesetRow.js +++ b/scm-ui/src/repos/components/ChangesetRow.js @@ -1,11 +1,13 @@ //@flow import React from "react"; -import type { Changeset } from "@scm-manager/ui-types"; +import type { Changeset, Repository } from "@scm-manager/ui-types"; 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 ChangesetAuthor from "./ChangesetAuthor"; const styles = { pointer: { @@ -13,10 +15,14 @@ const styles = { }, changesetGroup: { marginBottom: "1em" + }, + withOverflow: { + overflow: "auto" } }; type Props = { + repository: Repository, changeset: Changeset, t: any, classes: any @@ -24,32 +30,21 @@ type Props = { class ChangesetRow extends React.Component { createLink = (changeset: Changeset) => { - return {changeset.id}; + const { repository } = this.props; + return ; }; render() { - const { changeset, t, classes } = this.props; + const { changeset, classes } = this.props; const changesetLink = this.createLink(changeset); const dateFromNow = ; - const authorLine = ( - <> - {changeset.author.name}{" "} - - < - {changeset.author.mail} - > - - - ); + const authorLine = ; return (
-
+

{changeset.description} diff --git a/scm-ui/src/repos/components/ChangesetTable.js b/scm-ui/src/repos/components/ChangesetTable.js deleted file mode 100644 index 88c2b2fc3a..0000000000 --- a/scm-ui/src/repos/components/ChangesetTable.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow -import ChangesetRow from "./ChangesetRow"; -import React from "react"; -import type { Changeset } from "@scm-manager/ui-types"; -import classNames from "classnames"; - -type Props = { - changesets: Changeset[] -}; - -class ChangesetTable extends React.Component { - render() { - const { changesets } = this.props; - const content = changesets.map((changeset, index) => { - return ; - }); - return

{content}
; - } -} - -export default ChangesetTable; diff --git a/scm-ui/src/repos/containers/Changesets.js b/scm-ui/src/repos/containers/Changesets.js index 50bb0041c2..48a2f0d476 100644 --- a/scm-ui/src/repos/containers/Changesets.js +++ b/scm-ui/src/repos/containers/Changesets.js @@ -22,7 +22,7 @@ import { getBranchNames } from "../../repos/modules/branches"; import type { PagedCollection, Repository } from "@scm-manager/ui-types"; -import ChangesetTable from "../components/ChangesetTable"; +import ChangesetList from "../components/ChangesetList"; import DropDown from "../components/DropDown"; import { withRouter } from "react-router-dom"; @@ -84,7 +84,7 @@ class Changesets extends React.Component { renderTable = () => { const branch = this.props.match.params.branch; - const { changesets, branchNames } = this.props; + const { repository, changesets, branchNames } = this.props; if (branchNames && branchNames.length > 0) { return ( @@ -95,12 +95,12 @@ class Changesets extends React.Component { preselectedOption={branch} optionSelected={branch => this.branchChanged(branch)} /> - +
); } - return ; + return ; }; renderPaginator() { diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchRootResource.java index 9763f11def..80b8f7ddc7 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchRootResource.java @@ -100,9 +100,10 @@ public class BranchRootResource { try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) { Repository repository = repositoryService.getRepository(); RepositoryPermissions.read(repository).check(); - ChangesetPagingResult changesets = repositoryService.getLogCommand() - .setPagingStart(page) - .setPagingLimit(pageSize) + ChangesetPagingResult changesets = new PagedLogCommandBuilder(repositoryService) + .page(page) + .pageSize(pageSize) + .create() .setBranch(branchName) .getChangesets(); if (changesets != null && changesets.getChangesets() != null) { diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetRootResource.java index 717b8d7198..97a23684a5 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetRootResource.java @@ -12,6 +12,7 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryNotFoundException; import sonia.scm.repository.RepositoryPermissions; import sonia.scm.repository.RevisionNotFoundException; +import sonia.scm.repository.api.LogCommandBuilder; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.web.VndMediaType; @@ -59,9 +60,10 @@ public class ChangesetRootResource { try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) { Repository repository = repositoryService.getRepository(); RepositoryPermissions.read(repository).check(); - ChangesetPagingResult changesets = repositoryService.getLogCommand() - .setPagingStart(page) - .setPagingLimit(pageSize) + ChangesetPagingResult changesets = new PagedLogCommandBuilder(repositoryService) + .page(page) + .pageSize(pageSize) + .create() .getChangesets(); if (changesets != null && changesets.getChangesets() != null) { PageResult pageResult = new PageResult<>(changesets.getChangesets(), changesets.getTotal()); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/FileHistoryRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/FileHistoryRootResource.java index 118cc4167a..e38a6f699a 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/FileHistoryRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/FileHistoryRootResource.java @@ -73,9 +73,10 @@ public class FileHistoryRootResource { try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) { log.info("Get changesets of the file {} and revision {}", path, revision); Repository repository = repositoryService.getRepository(); - ChangesetPagingResult changesets = repositoryService.getLogCommand() - .setPagingStart(page) - .setPagingLimit(pageSize) + ChangesetPagingResult changesets = new PagedLogCommandBuilder(repositoryService) + .page(page) + .pageSize(pageSize) + .create() .setPath(path) .setStartChangeset(revision) .getChangesets(); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PagedLogCommandBuilder.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PagedLogCommandBuilder.java new file mode 100644 index 0000000000..c2af89e152 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PagedLogCommandBuilder.java @@ -0,0 +1,30 @@ +package sonia.scm.api.v2.resources; + +import sonia.scm.repository.api.LogCommandBuilder; +import sonia.scm.repository.api.RepositoryService; + +class PagedLogCommandBuilder { + private final RepositoryService repositoryService; + private int page; + private int pageSize ; + + PagedLogCommandBuilder(RepositoryService repositoryService) { + this.repositoryService = repositoryService; + } + + PagedLogCommandBuilder page(int page) { + this.page = page; + return this; + } + + PagedLogCommandBuilder pageSize(int pageSize) { + this.pageSize = pageSize; + return this; + } + + LogCommandBuilder create() { + return repositoryService.getLogCommand() + .setPagingStart(page * pageSize) + .setPagingLimit(pageSize); + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java index b80b62167b..4e1a0f90f1 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java @@ -109,8 +109,8 @@ public class ChangesetRootResourceTest extends RepositoryTestBase { List changesetList = Lists.newArrayList(new Changeset(id, Date.from(creationDate).getTime(), new Person(authorName, authorEmail), commit)); when(changesetPagingResult.getChangesets()).thenReturn(changesetList); when(changesetPagingResult.getTotal()).thenReturn(1); - when(logCommandBuilder.setPagingStart(anyInt())).thenReturn(logCommandBuilder); - when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder); + when(logCommandBuilder.setPagingStart(0)).thenReturn(logCommandBuilder); + when(logCommandBuilder.setPagingLimit(10)).thenReturn(logCommandBuilder); when(logCommandBuilder.setBranch(anyString())).thenReturn(logCommandBuilder); when(logCommandBuilder.getChangesets()).thenReturn(changesetPagingResult); MockHttpRequest request = MockHttpRequest @@ -126,6 +126,34 @@ public class ChangesetRootResourceTest extends RepositoryTestBase { assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit))); } + @Test + public void shouldGetSinglePageOfChangeSets() throws Exception { + String id = "revision_123"; + Instant creationDate = Instant.now(); + String authorName = "name"; + String authorEmail = "em@i.l"; + String commit = "my branch commit"; + ChangesetPagingResult changesetPagingResult = mock(ChangesetPagingResult.class); + List changesetList = Lists.newArrayList(new Changeset(id, Date.from(creationDate).getTime(), new Person(authorName, authorEmail), commit)); + when(changesetPagingResult.getChangesets()).thenReturn(changesetList); + when(changesetPagingResult.getTotal()).thenReturn(1); + when(logCommandBuilder.setPagingStart(20)).thenReturn(logCommandBuilder); + when(logCommandBuilder.setPagingLimit(10)).thenReturn(logCommandBuilder); + when(logCommandBuilder.setBranch(anyString())).thenReturn(logCommandBuilder); + when(logCommandBuilder.getChangesets()).thenReturn(changesetPagingResult); + MockHttpRequest request = MockHttpRequest + .get(CHANGESET_URL + "?page=2") + .accept(VndMediaType.CHANGESET_COLLECTION); + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + assertEquals(200, response.getStatus()); + log.info("Response :{}", response.getContentAsString()); + assertTrue(response.getContentAsString().contains(String.format("\"id\":\"%s\"", id))); + assertTrue(response.getContentAsString().contains(String.format("\"name\":\"%s\"", authorName))); + assertTrue(response.getContentAsString().contains(String.format("\"mail\":\"%s\"", authorEmail))); + assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit))); + } + @Test public void shouldGetChangeSet() throws Exception { String id = "revision_123"; @@ -137,8 +165,6 @@ public class ChangesetRootResourceTest extends RepositoryTestBase { List changesetList = Lists.newArrayList(new Changeset(id, Date.from(creationDate).getTime(), new Person(authorName, authorEmail), commit)); when(changesetPagingResult.getChangesets()).thenReturn(changesetList); when(changesetPagingResult.getTotal()).thenReturn(1); - when(logCommandBuilder.setPagingStart(anyInt())).thenReturn(logCommandBuilder); - when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder); when(logCommandBuilder.setEndChangeset(anyString())).thenReturn(logCommandBuilder); when(logCommandBuilder.setStartChangeset(anyString())).thenReturn(logCommandBuilder); when(logCommandBuilder.getChangesets()).thenReturn(changesetPagingResult);