From 9593a18a5551e307f70ca50eecb319e277b03736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maren=20S=C3=BCwer?= Date: Thu, 19 Jul 2018 11:23:20 +0200 Subject: [PATCH] add error notification if user deletion is unsuccessful and add DELETE_USER_SUCCESS --- scm-ui/src/users/containers/Users.js | 6 ++- scm-ui/src/users/modules/users.js | 73 ++++++++++++++++++++------ scm-ui/src/users/modules/users.test.js | 41 ++++++++++++++- 3 files changed, 101 insertions(+), 19 deletions(-) diff --git a/scm-ui/src/users/containers/Users.js b/scm-ui/src/users/containers/Users.js index 6c9793b89c..2d075717f4 100644 --- a/scm-ui/src/users/containers/Users.js +++ b/scm-ui/src/users/containers/Users.js @@ -51,9 +51,13 @@ class Users extends React.Component { const mapStateToProps = state => { const userEntries = getUsersFromState(state); + let error = null; + if (state.users && state.users.users) { + error = state.users.users.error + } return { userEntries, - error: state.users.error + error }; }; diff --git a/scm-ui/src/users/modules/users.js b/scm-ui/src/users/modules/users.js index 148cc2ece4..415b1d9e9a 100644 --- a/scm-ui/src/users/modules/users.js +++ b/scm-ui/src/users/modules/users.js @@ -1,8 +1,17 @@ // @flow -import { apiClient, NOT_FOUND_ERROR } from "../../apiclient"; -import type { User } from "../types/User"; -import type { UserEntry } from "../types/UserEntry"; -import { Dispatch } from "redux"; +import { + apiClient, + NOT_FOUND_ERROR +} from "../../apiclient"; +import type { + User +} from "../types/User"; +import type { + UserEntry +} from "../types/UserEntry"; +import { + Dispatch +} from "redux"; export const FETCH_USERS = "scm/users/FETCH"; export const FETCH_USERS_SUCCESS = "scm/users/FETCH_SUCCESS"; @@ -53,7 +62,7 @@ function usersNotFound(url: string) { } export function fetchUsers() { - return function(dispatch: any) { + return function (dispatch: any) { dispatch(requestUsers()); return apiClient .get(USERS_URL) @@ -96,7 +105,7 @@ function requestUser(name: string) { export function fetchUser(name: string) { const userUrl = USER_URL + name; - return function(dispatch: any) { + return function (dispatch: any) { dispatch(requestUsers()); return apiClient .get(userUrl) @@ -136,7 +145,7 @@ function requestAddUser(user: User) { } export function addUser(user: User) { - return function(dispatch: Dispatch) { + return function (dispatch: Dispatch) { dispatch(requestAddUser(user)); return apiClient .postWithContentType(USERS_URL, user, CONTENT_TYPE_USER) @@ -170,7 +179,7 @@ function requestUpdateUser(user: User) { } export function updateUser(user: User) { - return function(dispatch: Dispatch) { + return function (dispatch: Dispatch) { dispatch(requestUpdateUser(user)); return apiClient .putWithContentType(user._links.update.href, user, CONTENT_TYPE_USER) @@ -203,7 +212,7 @@ export function requestDeleteUser(user: User) { }; } -function deleteUserSuccess(user: User) { +export function deleteUserSuccess(user: User) { return { type: DELETE_USER_SUCCESS, payload: user @@ -221,7 +230,7 @@ export function deleteUserFailure(user: User, error: Error) { } export function deleteUser(user: User) { - return function(dispatch: any) { + return function (dispatch: any) { dispatch(requestDeleteUser(user)); return apiClient .delete(user._links.delete.href) @@ -229,7 +238,10 @@ export function deleteUser(user: User) { dispatch(deleteUserSuccess(user)); dispatch(fetchUsers()); }) - .catch(err => dispatch(deleteUserFailure(user, err))); + .catch(cause => { + const error = new Error(`could not delete user ${user.name}: ${cause.message}`); + dispatch(deleteUserFailure(user, error)); + }); }; } @@ -241,7 +253,7 @@ export function getUsersFromState(state) { if (!userNames) { return null; } - const userEntries: Array = []; + const userEntries: Array < UserEntry > = []; for (let userName of userNames) { userEntries.push(state.users.usersByNames[userName]); @@ -251,8 +263,8 @@ export function getUsersFromState(state) { } function extractUsersByNames( - users: Array, - userNames: Array, + users: Array < User > , + userNames: Array < string > , oldUsersByNames: {} ) { const usersByNames = {}; @@ -276,6 +288,24 @@ export function editUser(user: User) { }; } +function deleteUserInUsersByNames(users:{}, userName: any){ + let newUsers = {}; + for(let username in users){ + if(username != userName) + newUsers[username] = users[username]; + } + return newUsers; +} + +function deleteUserInEntries(users:[], userName: any){ + let newUsers = []; + for(let user of users){ + if(user != userName) + newUsers.push(user); + } + return newUsers; +} + const reduceUsersByNames = ( state: any, username: string, @@ -332,8 +362,7 @@ export default function reducer(state: any = {}, action: any = {}) { }; case FETCH_USER_SUCCESS: const ubn = extractUsersByNames( - [action.payload], - [action.payload.name], + [action.payload], [action.payload.name], state.usersByNames ); return { @@ -345,7 +374,17 @@ export default function reducer(state: any = {}, action: any = {}) { }, usersByNames: ubn }; - + case DELETE_USER_SUCCESS: + const newUserByNames = deleteUserInUsersByNames(state.usersByNames, [action.payload.name]); + const newUserEntries = deleteUserInEntries(state.users.entries, [action.payload.name]); + return { + ...state, + users: { + ...state.users, + entries: newUserEntries + }, + usersByNames: newUserByNames + } case FETCH_USERS_FAILURE: case DELETE_USER_FAILURE: const newState = reduceUsersByNames(state, action.payload.user.name, { diff --git a/scm-ui/src/users/modules/users.test.js b/scm-ui/src/users/modules/users.test.js index 7ec5b8c409..1eb38ca2fe 100644 --- a/scm-ui/src/users/modules/users.test.js +++ b/scm-ui/src/users/modules/users.test.js @@ -23,7 +23,8 @@ import { DELETE_USER_SUCCESS, DELETE_USER_FAILURE, deleteUser, - updateUserFailure + updateUserFailure, + deleteUserSuccess } from "./users"; import reducer from "./users"; @@ -365,6 +366,44 @@ describe("users reducer", () => { expect(ford.loading).toBeFalsy(); }); + it("should delete deleted user in users in state if delete user action is successful", () => { + const state = { + users: { + entries: [ + "zaphod", + "ford" + ] + } + }; + const newState = reducer(state, deleteUserSuccess(userZaphod)); + expect(newState.users.entries).toContain("ford"); + expect(newState.users.entries).not.toContain("zaphod"); + }); + + it("should delete deleted user in usersByNames in state if delete user action is successful", () => { + const state = { + users: { + entries: [ + "zaphod", + "ford" + ] + }, + usersByNames: { + zaphod: { + entry: userZaphod + }, + ford: { + entry: userFord + } + } + }; + const newState = reducer(state, deleteUserSuccess(userZaphod)); + const ford = newState.usersByNames["ford"]; + const zaphod = newState.usersByNames["zaphod"]; + expect(zaphod).toBeUndefined(); + expect(ford.entry).toBe(userFord); + }); + it("should set global error state if one user could not be deleted", () => { const state = { users: {