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 = (
- {buttons.map((button, i) => (
-
+ {buttons.map((button, index) => (
+
handleClickButton(button)}
>
{button.label}
diff --git a/scm-ui/ui-webapp/public/locales/de/repos.json b/scm-ui/ui-webapp/public/locales/de/repos.json
index d3ec72b23f..eceb488c3f 100644
--- a/scm-ui/ui-webapp/public/locales/de/repos.json
+++ b/scm-ui/ui-webapp/public/locales/de/repos.json
@@ -68,7 +68,19 @@
"name": "Name:",
"commits": "Commits",
"sources": "Sources",
- "defaultTag": "Default"
+ "defaultTag": "Default",
+ "dangerZone": "Branch löschen",
+ "delete": {
+ "button": "Branch löschen",
+ "subtitle": "Branch löschen",
+ "description": "Gelöschte Branches können nicht wiederhergestellt werden.",
+ "confirmAlert": {
+ "title": "Branch löschen",
+ "message": "Möchten Sie diesen Branch wirklich löschen?",
+ "cancel": "Nein",
+ "submit": "Ja"
+ }
+ }
},
"tags": {
"overview": {
diff --git a/scm-ui/ui-webapp/public/locales/en/repos.json b/scm-ui/ui-webapp/public/locales/en/repos.json
index 5f83ad7ba1..6845bf8b42 100644
--- a/scm-ui/ui-webapp/public/locales/en/repos.json
+++ b/scm-ui/ui-webapp/public/locales/en/repos.json
@@ -68,7 +68,19 @@
"name": "Name:",
"commits": "Commits",
"sources": "Sources",
- "defaultTag": "Default"
+ "defaultTag": "Default",
+ "dangerZone": "Delete branch",
+ "delete": {
+ "button": "Delete branch",
+ "subtitle": "Delete branch",
+ "description": "Deleted branches can not be restored.",
+ "confirmAlert": {
+ "title": "Delete branch",
+ "message": "Do you really want to delete the branch?",
+ "cancel": "No",
+ "submit": "Yes"
+ }
+ }
},
"tags": {
"overview": {
diff --git a/scm-ui/ui-webapp/src/repos/branches/components/BranchRow.tsx b/scm-ui/ui-webapp/src/repos/branches/components/BranchRow.tsx
index 6237bbe077..1c2df84b00 100644
--- a/scm-ui/ui-webapp/src/repos/branches/components/BranchRow.tsx
+++ b/scm-ui/ui-webapp/src/repos/branches/components/BranchRow.tsx
@@ -44,7 +44,7 @@ const BranchRow: FC = ({ baseUrl, branch, onDelete }) => {
deleteButton = (
onDelete(url)}>
-
+
);
diff --git a/scm-ui/ui-webapp/src/repos/branches/components/BranchTable.tsx b/scm-ui/ui-webapp/src/repos/branches/components/BranchTable.tsx
index 05589cffdd..ca45a8ee1c 100644
--- a/scm-ui/ui-webapp/src/repos/branches/components/BranchTable.tsx
+++ b/scm-ui/ui-webapp/src/repos/branches/components/BranchTable.tsx
@@ -21,19 +21,40 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-import React, { FC } from "react";
+import React, { FC, useState } from "react";
import { useTranslation } from "react-i18next";
import BranchRow from "./BranchRow";
import { Branch } from "@scm-manager/ui-types";
+import { apiClient, ConfirmAlert, ErrorNotification } from "@scm-manager/ui-components";
type Props = {
baseUrl: string;
branches: Branch[];
- onDelete: (url: string) => void;
+ fetchBranches: () => void;
};
-const BranchTable: FC = ({ baseUrl, branches, onDelete }) => {
+const BranchTable: FC = ({ baseUrl, branches, fetchBranches }) => {
const [t] = useTranslation("repos");
+ const [showConfirmAlert, setShowConfirmAlert] = useState(false);
+ const [error, setError] = useState();
+ const [deleteBranchUrl, setDeleteBranchUrl] = useState("");
+
+ const onDelete = (url: string) => {
+ setDeleteBranchUrl(url);
+ setShowConfirmAlert(true);
+ };
+
+ const abortDelete = () => {
+ setDeleteBranchUrl("");
+ setShowConfirmAlert(false);
+ };
+
+ const deleteBranch = () => {
+ apiClient
+ .delete(deleteBranchUrl)
+ .then(() => fetchBranches())
+ .catch(setError);
+ };
const renderRow = () => {
let rowContent = null;
@@ -44,15 +65,39 @@ const BranchTable: FC = ({ baseUrl, branches, onDelete }) => {
}
return rowContent;
};
+
+ const confirmAlert = (
+ deleteBranch()
+ },
+ {
+ label: t("branch.delete.confirmAlert.cancel"),
+ onClick: () => abortDelete()
+ }
+ ]}
+ close={() => abortDelete()}
+ />
+ );
+
return (
-
-
-
- | {t("branches.table.branches")} |
-
-
- {renderRow()}
-
+ <>
+ {showConfirmAlert && confirmAlert}
+ {error && }
+
+
+
+ | {t("branches.table.branches")} |
+
+
+ {renderRow()}
+
+ >
);
};
diff --git a/scm-ui/ui-webapp/src/repos/branches/components/BranchView.tsx b/scm-ui/ui-webapp/src/repos/branches/components/BranchView.tsx
index 9a88c08c2d..32ff0d8f7a 100644
--- a/scm-ui/ui-webapp/src/repos/branches/components/BranchView.tsx
+++ b/scm-ui/ui-webapp/src/repos/branches/components/BranchView.tsx
@@ -25,6 +25,7 @@ import React from "react";
import BranchDetail from "./BranchDetail";
import { ExtensionPoint } from "@scm-manager/ui-extensions";
import { Branch, Repository } from "@scm-manager/ui-types";
+import BranchDangerZone from "../containers/BranchDangerZone";
type Props = {
repository: Repository;
@@ -34,7 +35,6 @@ type Props = {
class BranchView extends React.Component {
render() {
const { repository, branch } = this.props;
-
return (
@@ -49,6 +49,7 @@ class BranchView extends React.Component
{
}}
/>
+
);
}
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 e18593a701..8bbcac53bf 100644
--- a/scm-ui/ui-webapp/src/repos/branches/containers/BranchesOverview.tsx
+++ b/scm-ui/ui-webapp/src/repos/branches/containers/BranchesOverview.tsx
@@ -37,7 +37,6 @@ import {
} from "../modules/branches";
import { orderBranches } from "../util/orderBranches";
import BranchTable from "../components/BranchTable";
-import { apiClient } from "@scm-manager/ui-components/src";
type Props = WithTranslation & {
repository: Repository;
@@ -81,15 +80,11 @@ class BranchesOverview extends React.Component {
);
}
- onDelete(url: string) {
- apiClient.delete(url).catch(error => this.setState({ error }));
- }
-
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..2ff9ff9284
--- /dev/null
+++ b/scm-ui/ui-webapp/src/repos/branches/containers/DeleteBranch.tsx
@@ -0,0 +1,94 @@
+/*
+ * 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();
+
+ console.log("branchview", repository, branch);
+
+ 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")}
+
+ }
+ right={ setShowConfirmAlert(true)} />}
+ />
+ >
+ );
+};
+
+export default DeleteBranch;
diff --git a/scm-ui/ui-webapp/src/repos/containers/EditRepo.tsx b/scm-ui/ui-webapp/src/repos/containers/EditRepo.tsx
index f2334c5d7e..2f91c8421b 100644
--- a/scm-ui/ui-webapp/src/repos/containers/EditRepo.tsx
+++ b/scm-ui/ui-webapp/src/repos/containers/EditRepo.tsx
@@ -31,7 +31,7 @@ import { History } from "history";
import { ErrorNotification } from "@scm-manager/ui-components";
import { ExtensionPoint } from "@scm-manager/ui-extensions";
import { compose } from "redux";
-import DangerZone from "./DangerZone";
+import RepositoryDangerZone from "./RepositoryDangerZone";
import { getLinks } from "../../modules/indexResource";
import { urls } from "@scm-manager/ui-components";
@@ -80,7 +80,7 @@ class EditRepo extends React.Component {
}}
/>
-
+
>
);
}
diff --git a/scm-ui/ui-webapp/src/repos/containers/DangerZone.tsx b/scm-ui/ui-webapp/src/repos/containers/RepositoryDangerZone.tsx
similarity index 93%
rename from scm-ui/ui-webapp/src/repos/containers/DangerZone.tsx
rename to scm-ui/ui-webapp/src/repos/containers/RepositoryDangerZone.tsx
index 0b2bda04b9..cb883a904f 100644
--- a/scm-ui/ui-webapp/src/repos/containers/DangerZone.tsx
+++ b/scm-ui/ui-webapp/src/repos/containers/RepositoryDangerZone.tsx
@@ -35,7 +35,7 @@ type Props = {
indexLinks: Links;
};
-const DangerZoneContainer = styled.div`
+export const DangerZoneContainer = styled.div`
padding: 1.5rem 1rem;
border: 1px solid #ff6a88;
border-radius: 5px;
@@ -56,7 +56,7 @@ const DangerZoneContainer = styled.div`
}
`;
-const DangerZone: FC = ({ repository, indexLinks }) => {
+const RepositoryDangerZone: FC = ({ repository, indexLinks }) => {
const [t] = useTranslation("repos");
const dangerZone = [];
@@ -81,4 +81,4 @@ const DangerZone: FC = ({ repository, indexLinks }) => {
);
};
-export default DangerZone;
+export default RepositoryDangerZone;