diff --git a/scm-ui/src/components/ConfirmAlert.css b/scm-ui/src/components/ConfirmAlert.css new file mode 100644 index 0000000000..96246a44a5 --- /dev/null +++ b/scm-ui/src/components/ConfirmAlert.css @@ -0,0 +1,102 @@ +/*modified from https://github.com/GA-MO/react-confirm-alert*/ +.react-confirm-alert-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 99; + background: rgba(255, 255, 255, 0.9); + display: -webkit-flex; + display: -moz-flex; + display: -ms-flex; + display: -o-flex; + display: flex; + justify-content: center; + -ms-align-items: center; + align-items: center; + opacity: 0; + -webkit-animation: react-confirm-alert-fadeIn 0.5s 0.2s forwards; + -moz-animation: react-confirm-alert-fadeIn 0.5s 0.2s forwards; + -o-animation: react-confirm-alert-fadeIn 0.5s 0.2s forwards; + animation: react-confirm-alert-fadeIn 0.5s 0.2s forwards; +} + +.react-confirm-alert-body { + font-family: Arial, Helvetica, sans-serif; + width: 400px; + padding: 30px; + text-align: left; + background: #fff; + border-radius: 10px; + box-shadow: 0 20px 75px rgba(0, 0, 0, 0.13); + color: #666; +} + +.react-confirm-alert-body > h1 { + margin-top: 0; +} + +.react-confirm-alert-body > h3 { + margin: 0; + font-size: 16px; +} + +.react-confirm-alert-button-group { + display: -webkit-flex; + display: -moz-flex; + display: -ms-flex; + display: -o-flex; + display: flex; + justify-content: flex-start; + margin-top: 20px; +} + +.react-confirm-alert-button-group > button { + outline: none; + background: #333; + border: none; + display: inline-block; + padding: 6px 18px; + color: #eee; + margin-right: 10px; + border-radius: 5px; + font-size: 12px; + cursor: pointer; +} + +@-webkit-keyframes react-confirm-alert-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-moz-keyframes react-confirm-alert-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-o-keyframes react-confirm-alert-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes react-confirm-alert-fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/scm-ui/src/components/ConfirmAlert.js b/scm-ui/src/components/ConfirmAlert.js new file mode 100644 index 0000000000..dce216acf4 --- /dev/null +++ b/scm-ui/src/components/ConfirmAlert.js @@ -0,0 +1,63 @@ +//modified from https://github.com/GA-MO/react-confirm-alert + +import React from "react"; +import { render, unmountComponentAtNode } from "react-dom"; + +type Props = { + title:string, + message: string, + buttons: array, +} + +class ConfirmAlert extends React.Component { + + handleClickButton = button => { + if (button.onClick) button.onClick() + this.close() + } + + close = () => { + removeElementReconfirm() + } + + render () { + const { title, message, buttons } = this.props; + + return ( +
+
+ {
+ {title &&

{title}

} + {message} +
+ {buttons.map((button, i) => ( + + ))} +
+
} +
+
+ ) + } +} + +function createElementReconfirm (properties) { + const divTarget = document.createElement('div') + divTarget.id = 'react-confirm-alert' + document.body.appendChild(divTarget) + render(, divTarget) +} + +function removeElementReconfirm () { + const target = document.getElementById('react-confirm-alert') + unmountComponentAtNode(target) + target.parentNode.removeChild(target) +} + +export function confirmAlert (properties) { + createElementReconfirm(properties) +} + +export default ConfirmAlert; diff --git a/scm-ui/src/containers/App.js b/scm-ui/src/containers/App.js index a8140a0f94..fbde1036fd 100644 --- a/scm-ui/src/containers/App.js +++ b/scm-ui/src/containers/App.js @@ -8,6 +8,7 @@ import { fetchMe } from "../modules/me"; import { logout } from "../modules/auth"; import "./App.css"; +import "../components/ConfirmAlert.css"; import Header from "../components/Header"; import PrimaryNavigation from "../components/PrimaryNavigation"; import Loading from "../components/Loading"; diff --git a/scm-ui/src/users/containers/DeleteUserButton.js b/scm-ui/src/users/containers/DeleteUserButton.js index 0bd7180505..0ecaaa74be 100644 --- a/scm-ui/src/users/containers/DeleteUserButton.js +++ b/scm-ui/src/users/containers/DeleteUserButton.js @@ -1,28 +1,56 @@ // @flow import React from "react"; -import type { User } from "../types/User"; +import type { + User +} from "../types/User"; +import { + confirmAlert +} from '../../components/ConfirmAlert'; type Props = { user: User, deleteUser: (link: string) => void, }; -class DeleteUserButton extends React.Component { +class DeleteUserButton extends React.Component < Props > { deleteUser = () => { this.props.deleteUser(this.props.user._links.delete.href); }; + confirmDelete = () => { + confirmAlert({ + title: 'Delete user', + message: 'Do you really want to delete the user?', + buttons: [{ + label: 'Yes', + onClick: () => this.deleteUser() + }, + { + label: 'No', + onClick: () => null + } + ] + }) + } + isDeletable = () => { return this.props.user._links.delete; }; render() { - return ( - - + if (!this.isDeletable()) { + return; + } + return ( < + button type = "button" + onClick = { + (e) => { + this.confirmDelete() + } + } > + Delete User < + /button> ); } } diff --git a/scm-ui/src/users/containers/DeleteUserButton.test.js b/scm-ui/src/users/containers/DeleteUserButton.test.js index 4e1a1af663..937ee81172 100644 --- a/scm-ui/src/users/containers/DeleteUserButton.test.js +++ b/scm-ui/src/users/containers/DeleteUserButton.test.js @@ -29,6 +29,7 @@ it("should render the button", () => { expect(button.text()).not.toBe(""); }); +//TODO: Fix wrong test! it("should call the delete user function with delete url", () => { const user = { _links: { diff --git a/scm-ui/src/users/modules/users.js b/scm-ui/src/users/modules/users.js index cba960b484..50c7fcef82 100644 --- a/scm-ui/src/users/modules/users.js +++ b/scm-ui/src/users/modules/users.js @@ -167,6 +167,7 @@ function deleteUserFailure(url: string, err: Error) { } export function deleteUser(link: string) { + return function(dispatch: ThunkDispatch) { dispatch(requestDeleteUser(link)); return apiClient @@ -177,6 +178,7 @@ export function deleteUser(link: string) { }) .catch(err => dispatch(deleteUserFailure(link, err))); }; + } export default function reducer(state: any = {}, action: any = {}) {