diff --git a/CHANGELOG.md b/CHANGELOG.md
index 59fddd12c3..dd06aa41ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
+- Delete branches directly in the UI ([#1422](https://github.com/scm-manager/scm-manager/pull/1422))
- Lookup command which provides further repository information ([#1415](https://github.com/scm-manager/scm-manager/pull/1415))
- Include messages from scm protocol in modification or merge errors ([#1420](https://github.com/scm-manager/scm-manager/pull/1420))
diff --git a/docs/de/user/repo/assets/repository-branch-detailView.png b/docs/de/user/repo/assets/repository-branch-detailView.png
index a73b369e26..d671846fef 100644
Binary files a/docs/de/user/repo/assets/repository-branch-detailView.png and b/docs/de/user/repo/assets/repository-branch-detailView.png differ
diff --git a/docs/de/user/repo/assets/repository-branches-overview.png b/docs/de/user/repo/assets/repository-branches-overview.png
index 9258f4be97..39dcf5e424 100644
Binary files a/docs/de/user/repo/assets/repository-branches-overview.png and b/docs/de/user/repo/assets/repository-branches-overview.png differ
diff --git a/docs/de/user/repo/branches.md b/docs/de/user/repo/branches.md
index b52b6492b2..17afe92924 100644
--- a/docs/de/user/repo/branches.md
+++ b/docs/de/user/repo/branches.md
@@ -6,6 +6,7 @@ subtitle: Branches
Auf der Branches-Übersicht sind die bereits existierenden Branches aufgeführt. Bei einem Klick auf einen Branch wird man zur Detailseite des Branches weitergeleitet.
Der Tag "Default" gibt an welcher Branch aktuell, als Standard-Branch dieses Repository im SCM-Manager markiert ist. Der Standard-Branch wird immer zuerst angezeigt, wenn man das Repository im SCM-Manager öffnet.
+Alle Branches mit Ausnahme des Default Branches können über den Mülleimer-Icon unwiderruflich gelöscht werden.
Über den "Branch erstellen"-Button gelangt man zum Formular, um neue Branches anzulegen.
@@ -19,4 +20,6 @@ Mit dem "Branch erstellen"-Formular können neue Branches für das Repository er
### Branch Detailseite
Hier werden einige Befehle zum Arbeiten mit dem Branch auf einer Kommandozeile aufgeführt.
+Handelt es sich nicht um den Default Branch des Repositories, kann im unteren Bereich der Branch unwiderruflich gelöscht werden.
+

diff --git a/docs/en/user/repo/assets/repository-branch-detailView.png b/docs/en/user/repo/assets/repository-branch-detailView.png
index 2660d58a82..615ba696c1 100644
Binary files a/docs/en/user/repo/assets/repository-branch-detailView.png and b/docs/en/user/repo/assets/repository-branch-detailView.png differ
diff --git a/docs/en/user/repo/assets/repository-branches-overview.png b/docs/en/user/repo/assets/repository-branches-overview.png
index 32560b4f31..e63ebab775 100644
Binary files a/docs/en/user/repo/assets/repository-branches-overview.png and b/docs/en/user/repo/assets/repository-branches-overview.png differ
diff --git a/docs/en/user/repo/branches.md b/docs/en/user/repo/branches.md
index 8c39eae6f0..370165710b 100644
--- a/docs/en/user/repo/branches.md
+++ b/docs/en/user/repo/branches.md
@@ -6,6 +6,7 @@ subtitle: Branches
The branches overview shows the branches that are already existing. By clicking on a branch, the details page of the branch is shown.
The tag "Default" shows which branch is currently set as the default branch of the repository in SCM-Manager. The default branch is always shown first when opening the repository in SCM-Manager.
+All branches except the default branch of the repository can be deleted by clicking on the trash bin icon.
The button "Create Branch" opens the form to create a new branch.
@@ -18,5 +19,6 @@ New branches can be created with the "Create Branch" form. There, you have to ch
### Branch Details Page
This page shows some commands to work with the branch on the command line.
+If the branch is not the default branch of the repository it can be deleted using the action inside the bottom section.

diff --git a/scm-ui/ui-components/src/modals/ConfirmAlert.tsx b/scm-ui/ui-components/src/modals/ConfirmAlert.tsx
index 89f8f0a117..290f024b63 100644
--- a/scm-ui/ui-components/src/modals/ConfirmAlert.tsx
+++ b/scm-ui/ui-components/src/modals/ConfirmAlert.tsx
@@ -62,11 +62,11 @@ export const ConfirmAlert: FC = ({ title, message, buttons, close }) => {
const footer = (
);
}
diff --git a/scm-ui/ui-webapp/src/repos/branches/containers/BranchDangerZone.tsx b/scm-ui/ui-webapp/src/repos/branches/containers/BranchDangerZone.tsx
new file mode 100644
index 0000000000..9e6c0e167a
--- /dev/null
+++ b/scm-ui/ui-webapp/src/repos/branches/containers/BranchDangerZone.tsx
@@ -0,0 +1,59 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React, { FC } from "react";
+import { Branch, Repository } from "@scm-manager/ui-types";
+import { Subtitle } from "@scm-manager/ui-components";
+import { useTranslation } from "react-i18next";
+import { DangerZoneContainer } from "../../containers/RepositoryDangerZone";
+import DeleteBranch from "./DeleteBranch";
+
+type Props = {
+ repository: Repository;
+ branch: Branch;
+};
+
+const BranchDangerZone: FC = ({ repository, branch }) => {
+ const [t] = useTranslation("repos");
+
+ const dangerZone = [];
+
+ if (branch?._links?.delete) {
+ dangerZone.push();
+ }
+
+ if (dangerZone.length === 0) {
+ return null;
+ }
+
+ return (
+ <>
+
+
+ {dangerZone}
+ >
+ );
+};
+
+export default BranchDangerZone;
diff --git a/scm-ui/ui-webapp/src/repos/branches/containers/BranchRoot.tsx b/scm-ui/ui-webapp/src/repos/branches/containers/BranchRoot.tsx
index cb2847a712..9a9aa02d24 100644
--- a/scm-ui/ui-webapp/src/repos/branches/containers/BranchRoot.tsx
+++ b/scm-ui/ui-webapp/src/repos/branches/containers/BranchRoot.tsx
@@ -28,10 +28,9 @@ import { compose } from "redux";
import { Redirect, Route, Switch, withRouter } from "react-router-dom";
import { Branch, Repository } from "@scm-manager/ui-types";
import { fetchBranch, getBranch, getFetchBranchFailure, isFetchBranchPending } from "../modules/branches";
-import { ErrorNotification, Loading, NotFoundError } from "@scm-manager/ui-components";
+import { ErrorNotification, Loading, NotFoundError, urls } from "@scm-manager/ui-components";
import { History } from "history";
import queryString from "query-string";
-import { urls } from "@scm-manager/ui-components";
type Props = {
repository: Repository;
diff --git a/scm-ui/ui-webapp/src/repos/branches/containers/BranchesOverview.tsx b/scm-ui/ui-webapp/src/repos/branches/containers/BranchesOverview.tsx
index 0e2a01622b..8bbcac53bf 100644
--- a/scm-ui/ui-webapp/src/repos/branches/containers/BranchesOverview.tsx
+++ b/scm-ui/ui-webapp/src/repos/branches/containers/BranchesOverview.tsx
@@ -81,10 +81,10 @@ class BranchesOverview extends React.Component {
}
renderBranchesTable() {
- const { baseUrl, branches, t } = this.props;
+ const { baseUrl, branches, repository, fetchBranches, t } = this.props;
if (branches && branches.length > 0) {
orderBranches(branches);
- return ;
+ return fetchBranches(repository)} />;
}
return {t("branches.overview.noBranches")};
}
diff --git a/scm-ui/ui-webapp/src/repos/branches/containers/DeleteBranch.tsx b/scm-ui/ui-webapp/src/repos/branches/containers/DeleteBranch.tsx
new file mode 100644
index 0000000000..820c09740b
--- /dev/null
+++ b/scm-ui/ui-webapp/src/repos/branches/containers/DeleteBranch.tsx
@@ -0,0 +1,92 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+import React, { FC, useState } from "react";
+import { useHistory } from "react-router-dom";
+import { useTranslation } from "react-i18next";
+import { Branch, Link, Repository } from "@scm-manager/ui-types";
+import { apiClient, ConfirmAlert, DeleteButton, ErrorNotification, Level } from "@scm-manager/ui-components";
+
+type Props = {
+ repository: Repository;
+ branch: Branch;
+};
+
+const DeleteBranch: FC = ({ repository, branch }: Props) => {
+ const [showConfirmAlert, setShowConfirmAlert] = useState(false);
+ const [error, setError] = useState();
+ const [t] = useTranslation("repos");
+ const history = useHistory();
+
+ const deleteBranch = () => {
+ apiClient
+ .delete((branch._links.delete as Link).href)
+ .then(() => history.push(`/repo/${repository.namespace}/${repository.name}/branches/`))
+ .catch(setError);
+ };
+
+ if (!branch._links.delete) {
+ return null;
+ }
+
+ let confirmAlert = null;
+ if (showConfirmAlert) {
+ confirmAlert = (
+ deleteBranch()
+ },
+ {
+ label: t("branch.delete.confirmAlert.cancel"),
+ onClick: () => null
+ }
+ ]}
+ close={() => setShowConfirmAlert(false)}
+ />
+ );
+ }
+
+ return (
+ <>
+
+ {showConfirmAlert && confirmAlert}
+
+ {t("branch.delete.subtitle")}
+
+ {t("branch.delete.description")}
+