mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-03-06 12:20:56 +01:00
Merged in feature/redirect_issuetracker_links (pull request #283)
Feature/redirect issuetracker links
This commit is contained in:
20
scm-plugins/scm-legacy-plugin/package.json
Normal file
20
scm-plugins/scm-legacy-plugin/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@scm-manager/legacy-plugin",
|
||||
"license": "BSD-3-Clause",
|
||||
"main": "src/main/js/index.js",
|
||||
"scripts": {
|
||||
"build": "ui-bundler plugin",
|
||||
"watch": "ui-bundler plugin -w",
|
||||
"lint": "ui-bundler lint",
|
||||
"flow": "flow check"
|
||||
},
|
||||
"dependencies": {
|
||||
"@scm-manager/ui-components": "latest",
|
||||
"@scm-manager/ui-extensions": "^0.1.1",
|
||||
"react-redux": "^5.0.7",
|
||||
"@scm-manager/ui-types": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scm-manager/ui-bundler": "^0.0.25"
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,13 @@
|
||||
<version>${servlet.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package sonia.scm.legacy;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import sonia.scm.api.v2.resources.Enrich;
|
||||
import sonia.scm.api.v2.resources.HalAppender;
|
||||
import sonia.scm.api.v2.resources.HalEnricher;
|
||||
import sonia.scm.api.v2.resources.HalEnricherContext;
|
||||
import sonia.scm.api.v2.resources.Index;
|
||||
import sonia.scm.api.v2.resources.LinkBuilder;
|
||||
import sonia.scm.api.v2.resources.ScmPathInfoStore;
|
||||
import sonia.scm.plugin.Extension;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
@Extension
|
||||
@Enrich(Index.class)
|
||||
public class LegacyIndexHalEnricher implements HalEnricher {
|
||||
|
||||
private Provider<ScmPathInfoStore> scmPathInfoStoreProvider;
|
||||
|
||||
@Inject
|
||||
public LegacyIndexHalEnricher(Provider<ScmPathInfoStore> scmPathInfoStoreProvider) {
|
||||
this.scmPathInfoStoreProvider = scmPathInfoStoreProvider;
|
||||
}
|
||||
|
||||
private String createLink() {
|
||||
return new LinkBuilder(scmPathInfoStoreProvider.get().get(), LegacyRepositoryService.class)
|
||||
.method("getNameAndNamespaceForRepositoryId")
|
||||
.parameters("REPOID")
|
||||
.href()
|
||||
.replace("REPOID", "{id}");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enrich(HalEnricherContext context, HalAppender appender) {
|
||||
appender.appendLink("nameAndNamespace", createLink());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package sonia.scm.legacy;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
@Path("v2/legacy/repository")
|
||||
public class LegacyRepositoryService {
|
||||
|
||||
private RepositoryManager repositoryManager;
|
||||
|
||||
@Inject
|
||||
public LegacyRepositoryService(RepositoryManager repositoryManager) {
|
||||
this.repositoryManager = repositoryManager;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user does not have the \"repository:read:global\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public NamespaceAndNameDto getNameAndNamespaceForRepositoryId(@PathParam("id") String repositoryId) {
|
||||
Repository repo = repositoryManager.get(repositoryId);
|
||||
if (repo == null) {
|
||||
throw new NotFoundException(Repository.class, repositoryId);
|
||||
}
|
||||
return new NamespaceAndNameDto(repo.getName(), repo.getNamespace());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package sonia.scm.legacy;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class NamespaceAndNameDto {
|
||||
private String name;
|
||||
private String namespace;
|
||||
}
|
||||
14
scm-plugins/scm-legacy-plugin/src/main/js/DummyComponent.js
Normal file
14
scm-plugins/scm-legacy-plugin/src/main/js/DummyComponent.js
Normal file
@@ -0,0 +1,14 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { withRouter } from "react-router-dom";
|
||||
|
||||
class DummyComponent extends React.Component<Props, State> {
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(DummyComponent);
|
||||
95
scm-plugins/scm-legacy-plugin/src/main/js/index.js
Normal file
95
scm-plugins/scm-legacy-plugin/src/main/js/index.js
Normal file
@@ -0,0 +1,95 @@
|
||||
// @flow
|
||||
|
||||
import React from "react";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import { binder } from "@scm-manager/ui-extensions";
|
||||
import {
|
||||
ProtectedRoute,
|
||||
apiClient,
|
||||
ErrorNotification,
|
||||
ErrorBoundary
|
||||
} from "@scm-manager/ui-components";
|
||||
import DummyComponent from "./DummyComponent";
|
||||
import type {Links} from "@scm-manager/ui-types";
|
||||
|
||||
type Props = {
|
||||
authenticated?: boolean,
|
||||
links: Links,
|
||||
|
||||
//context objects
|
||||
history: History
|
||||
};
|
||||
|
||||
type State = {
|
||||
error?: Error
|
||||
};
|
||||
|
||||
class LegacyRepositoryRedirect extends React.Component<Props, State> {
|
||||
constructor(props: Props, state: State) {
|
||||
super(props, state);
|
||||
this.state = { error: null };
|
||||
}
|
||||
|
||||
handleError = (error: Error) => {
|
||||
this.setState({
|
||||
error
|
||||
});
|
||||
};
|
||||
|
||||
redirectLegacyRepository() {
|
||||
const { history, links } = this.props;
|
||||
if (location.href && location.href.includes("#diffPanel;")) {
|
||||
let splittedUrl = location.href.split(";");
|
||||
let repoId = splittedUrl[1];
|
||||
let changeSetId = splittedUrl[2];
|
||||
|
||||
apiClient
|
||||
.get(links.nameAndNamespace.href.replace("{id}", repoId))
|
||||
.then(response => response.json())
|
||||
.then(payload =>
|
||||
history.push(
|
||||
"/repo/" +
|
||||
payload.namespace +
|
||||
"/" +
|
||||
payload.name +
|
||||
"/changeset/" +
|
||||
changeSetId
|
||||
)
|
||||
)
|
||||
.catch(this.handleError);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { authenticated } = this.props;
|
||||
const { error } = this.state;
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<ErrorBoundary>
|
||||
<ErrorNotification error={error} />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{authenticated ? (
|
||||
this.redirectLegacyRepository()
|
||||
) : (
|
||||
<ProtectedRoute
|
||||
path="/index.html"
|
||||
component={DummyComponent}
|
||||
authenticated={authenticated}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
binder.bind("main.route", withRouter(LegacyRepositoryRedirect));
|
||||
@@ -0,0 +1,43 @@
|
||||
package sonia.scm.legacy;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LegacyRepositoryServiceTest {
|
||||
|
||||
@Mock
|
||||
private RepositoryManager repositoryManager;
|
||||
|
||||
private LegacyRepositoryService legacyRepositoryService;
|
||||
private final Repository repository = new Repository("abc123", "git", "space", "repo");
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
legacyRepositoryService = new LegacyRepositoryService(repositoryManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findRepositoryNameSpaceAndNameForRepositoryId() {
|
||||
when(repositoryManager.get(any(String.class))).thenReturn(repository);
|
||||
NamespaceAndNameDto namespaceAndName = legacyRepositoryService.getNameAndNamespaceForRepositoryId("abc123");
|
||||
assertThat(namespaceAndName.getName()).isEqualToIgnoringCase("repo");
|
||||
assertThat(namespaceAndName.getNamespace()).isEqualToIgnoringCase("space");
|
||||
}
|
||||
|
||||
@Test(expected = NotFoundException.class)
|
||||
public void shouldGetNotFoundExceptionIfRepositoryNotExists() throws NotFoundException {
|
||||
when(repositoryManager.get(any(String.class))).thenReturn(null);
|
||||
legacyRepositoryService.getNameAndNamespaceForRepositoryId("456def");
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,6 @@ class Main extends React.Component<Props> {
|
||||
component={Profile}
|
||||
authenticated={authenticated}
|
||||
/>
|
||||
|
||||
<ExtensionPoint
|
||||
name="main.route"
|
||||
renderAll={true}
|
||||
|
||||
Reference in New Issue
Block a user