From 5cf62bf345443945a52e7bcc82bf68397f489a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maren=20S=C3=BCwer?= Date: Thu, 2 Aug 2018 09:53:24 +0200 Subject: [PATCH] added delete group function --- scm-ui/public/locales/en/groups.json | 9 +++ .../components/navLinks/DeleteGroupNavLink.js | 57 +++++++++++++ .../navLinks/DeleteGroupNavLink.test.js | 79 +++++++++++++++++++ .../src/groups/components/navLinks/index.js | 2 + scm-ui/src/groups/containers/SingleGroup.js | 22 +++++- 5 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 scm-ui/src/groups/components/navLinks/DeleteGroupNavLink.js create mode 100644 scm-ui/src/groups/components/navLinks/DeleteGroupNavLink.test.js create mode 100644 scm-ui/src/groups/components/navLinks/index.js diff --git a/scm-ui/public/locales/en/groups.json b/scm-ui/public/locales/en/groups.json index 16c8dae0ec..3484134901 100644 --- a/scm-ui/public/locales/en/groups.json +++ b/scm-ui/public/locales/en/groups.json @@ -31,5 +31,14 @@ }, "group-form": { "submit": "Submit" + }, + "delete-group-button": { + "label": "Delete", + "confirm-alert": { + "title": "Delete Group", + "message": "Do you really want to delete the group?", + "submit": "Yes", + "cancel": "No" + } } } diff --git a/scm-ui/src/groups/components/navLinks/DeleteGroupNavLink.js b/scm-ui/src/groups/components/navLinks/DeleteGroupNavLink.js new file mode 100644 index 0000000000..a54865e1e7 --- /dev/null +++ b/scm-ui/src/groups/components/navLinks/DeleteGroupNavLink.js @@ -0,0 +1,57 @@ +// @flow +import React from "react"; +import { translate } from "react-i18next"; +import type { Group } from "../../types/Group"; +import { confirmAlert } from "../../../components/modals/ConfirmAlert"; +import { NavAction } from "../../../components/navigation"; + +type Props = { + group: Group, + confirmDialog?: boolean, + t: string => string, + deleteGroup: (group: Group) => void +}; + +export class DeleteGroupNavLink extends React.Component { + static defaultProps = { + confirmDialog: true + }; + + deleteGroup = () => { + this.props.deleteGroup(this.props.group); + }; + + confirmDelete = () => { + const { t } = this.props; + confirmAlert({ + title: t("delete-group-button.confirm-alert.title"), + message: t("delete-group-button.confirm-alert.message"), + buttons: [ + { + label: t("delete-group-button.confirm-alert.submit"), + onClick: () => this.deleteGroup() + }, + { + label: t("delete-group-button.confirm-alert.cancel"), + onClick: () => null + } + ] + }); + }; + + isDeletable = () => { + return this.props.group._links.delete; + }; + + render() { + const { confirmDialog, t } = this.props; + const action = confirmDialog ? this.confirmDelete : this.deleteGroup; + + if (!this.isDeletable()) { + return null; + } + return ; + } +} + +export default translate("groups")(DeleteGroupNavLink); diff --git a/scm-ui/src/groups/components/navLinks/DeleteGroupNavLink.test.js b/scm-ui/src/groups/components/navLinks/DeleteGroupNavLink.test.js new file mode 100644 index 0000000000..eec9e164ca --- /dev/null +++ b/scm-ui/src/groups/components/navLinks/DeleteGroupNavLink.test.js @@ -0,0 +1,79 @@ +import React from "react"; +import { mount, shallow } from "enzyme"; +import "../../../tests/enzyme"; +import "../../../tests/i18n"; +import DeleteGroupNavLink from "./DeleteGroupNavLink"; + +import { confirmAlert } from "../../../components/modals/ConfirmAlert"; +jest.mock("../../../components/modals/ConfirmAlert"); + +describe("DeleteGroupNavLink", () => { + it("should render nothing, if the delete link is missing", () => { + const group = { + _links: {} + }; + + const navLink = shallow( + {}} /> + ); + expect(navLink.text()).toBe(""); + }); + + it("should render the navLink", () => { + const group = { + _links: { + delete: { + href: "/groups" + } + } + }; + + const navLink = mount( + {}} /> + ); + expect(navLink.text()).not.toBe(""); + }); + + it("should open the confirm dialog on navLink click", () => { + const group = { + _links: { + delete: { + href: "/groups" + } + } + }; + + const navLink = mount( + {}} /> + ); + navLink.find("a").simulate("click"); + + expect(confirmAlert.mock.calls.length).toBe(1); + }); + + it("should call the delete group function with delete url", () => { + const group = { + _links: { + delete: { + href: "/groups" + } + } + }; + + let calledUrl = null; + function capture(group) { + calledUrl = group._links.delete.href; + } + + const navLink = mount( + + ); + navLink.find("a").simulate("click"); + + expect(calledUrl).toBe("/groups"); + }); +}); diff --git a/scm-ui/src/groups/components/navLinks/index.js b/scm-ui/src/groups/components/navLinks/index.js new file mode 100644 index 0000000000..30fdd34b6d --- /dev/null +++ b/scm-ui/src/groups/components/navLinks/index.js @@ -0,0 +1,2 @@ +export { default as DeleteGroupNavLink } from "./DeleteGroupNavLink"; +export { default as EditGroupNavLink } from "./EditGroupNavLink"; diff --git a/scm-ui/src/groups/containers/SingleGroup.js b/scm-ui/src/groups/containers/SingleGroup.js index 2319801cf8..7f162fbdde 100644 --- a/scm-ui/src/groups/containers/SingleGroup.js +++ b/scm-ui/src/groups/containers/SingleGroup.js @@ -4,20 +4,23 @@ import { connect } from "react-redux"; import { Page } from "../../components/layout"; import { Route } from "react-router"; import { Details } from "./../components/table"; +import { DeleteGroupNavLink, EditGroupNavLink } from "./../components/navLinks"; import type { Group } from "../types/Group"; import type { History } from "history"; import { + deleteGroup, fetchGroup, getGroupByName, isFetchGroupPending, getFetchGroupFailure, + getDeleteGroupFailure, + isDeleteGroupPending, } from "../modules/groups"; import Loading from "../../components/Loading"; import { Navigation, Section, NavLink } from "../../components/navigation"; import ErrorPage from "../../components/ErrorPage"; import { translate } from "react-i18next"; -import EditGroupNavLink from "../components/navLinks/EditGroupNavLink"; type Props = { name: string, @@ -26,6 +29,7 @@ type Props = { error: Error, // dispatcher functions + deleteGroup: (group: Group, callback?: () => void) => void, fetchGroup: string => void, // context objects @@ -46,6 +50,14 @@ class SingleGroup extends React.Component { return url; }; + deleteGroup = (group: Group) => { + this.props.deleteGroup(group, this.groupDeleted); + }; + + groupDeleted = () => { + this.props.history.push("/groups"); + }; + matchedUrl = () => { return this.stripEndingSlash(this.props.match.url); }; @@ -84,6 +96,7 @@ class SingleGroup extends React.Component { />
+
@@ -99,9 +112,9 @@ const mapStateToProps = (state, ownProps) => { const name = ownProps.match.params.name; const group = getGroupByName(state, name); const loading = - isFetchGroupPending(state, name); + isFetchGroupPending(state, name) || isDeleteGroupPending(state, name); const error = - getFetchGroupFailure(state, name); + getFetchGroupFailure(state, name) || getDeleteGroupFailure(state, name); return { name, @@ -116,6 +129,9 @@ const mapDispatchToProps = dispatch => { fetchGroup: (name: string) => { dispatch(fetchGroup(name)); }, + deleteGroup: (group: Group, callback?: () => void) => { + dispatch(deleteGroup(group, callback)); + } }; };