mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-08 14:35:45 +01:00
Implemented editing of users
This commit is contained in:
@@ -3,6 +3,7 @@ import React from "react";
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string,
|
label: string,
|
||||||
|
checked: boolean,
|
||||||
onChange: boolean => void
|
onChange: boolean => void
|
||||||
};
|
};
|
||||||
class Checkbox extends React.Component<Props> {
|
class Checkbox extends React.Component<Props> {
|
||||||
@@ -15,7 +16,11 @@ class Checkbox extends React.Component<Props> {
|
|||||||
<div className="field">
|
<div className="field">
|
||||||
<div className="control">
|
<div className="control">
|
||||||
<label className="checkbox">
|
<label className="checkbox">
|
||||||
<input type="checkbox" onChange={this.onCheckboxChange} />{" "}
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={this.props.checked}
|
||||||
|
onChange={this.onCheckboxChange}
|
||||||
|
/>
|
||||||
{this.props.label}
|
{this.props.label}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import React from "react";
|
|||||||
type Props = {
|
type Props = {
|
||||||
label?: string,
|
label?: string,
|
||||||
placeholder?: string,
|
placeholder?: string,
|
||||||
|
value?: string,
|
||||||
type?: string,
|
type?: string,
|
||||||
autofocus?: boolean,
|
autofocus?: boolean,
|
||||||
onChange: string => void
|
onChange: string => void
|
||||||
@@ -36,7 +37,7 @@ class InputField extends React.Component<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { type, placeholder } = this.props;
|
const { type, placeholder, value } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="field">
|
<div className="field">
|
||||||
@@ -49,6 +50,7 @@ class InputField extends React.Component<Props> {
|
|||||||
className="input"
|
className="input"
|
||||||
type={type}
|
type={type}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
value={value}
|
||||||
onChange={this.handleInput}
|
onChange={this.handleInput}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,46 +11,63 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class UserForm extends React.Component<Props, User> {
|
class UserForm extends React.Component<Props, User> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
name: "",
|
||||||
|
displayName: "",
|
||||||
|
mail: "",
|
||||||
|
password: "",
|
||||||
|
admin: false,
|
||||||
|
active: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
submit = (event: Event) => {
|
submit = (event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.props.submitForm(this.state);
|
this.props.submitForm(this.state);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
componentWillReceiveProps() {
|
||||||
|
this.setState(this.props.user);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { submitForm, user } = this.props;
|
const { submitForm } = this.props;
|
||||||
|
const user = this.state;
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<form onSubmit={this.submit}>
|
<form onSubmit={this.submit}>
|
||||||
<InputField
|
<InputField
|
||||||
label="Username"
|
label="Username"
|
||||||
onChange={this.handleUsernameChange}
|
onChange={this.handleUsernameChange}
|
||||||
value={user !== undefined ? user.name : ""}
|
value={user ? user.name : ""}
|
||||||
/>
|
/>
|
||||||
<InputField
|
<InputField
|
||||||
label="Display Name"
|
label="Display Name"
|
||||||
onChange={this.handleDisplayNameChange}
|
onChange={this.handleDisplayNameChange}
|
||||||
value={user !== undefined ? user.displayName : ""}
|
value={user ? user.displayName : ""}
|
||||||
/>
|
/>
|
||||||
<InputField
|
<InputField
|
||||||
label="E-Mail"
|
label="E-Mail"
|
||||||
onChange={this.handleEmailChange}
|
onChange={this.handleEmailChange}
|
||||||
value={user !== undefined ? user.mail : ""}
|
value={user ? user.mail : ""}
|
||||||
/>
|
/>
|
||||||
<InputField
|
<InputField
|
||||||
label="Password"
|
label="Password"
|
||||||
type="password"
|
type="password"
|
||||||
onChange={this.handlePasswordChange}
|
onChange={this.handlePasswordChange}
|
||||||
value={user !== undefined ? user.password : ""}
|
value={user ? user.password : ""}
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Admin"
|
label="Admin"
|
||||||
onChange={this.handleAdminChange}
|
onChange={this.handleAdminChange}
|
||||||
checked={user !== undefined ? user.admin : false}
|
checked={user ? user.admin : false}
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Active"
|
label="Active"
|
||||||
onChange={this.handleActiveChange}
|
onChange={this.handleActiveChange}
|
||||||
value={user !== undefined ? user.active : false}
|
checked={user ? user.active : false}
|
||||||
/>
|
/>
|
||||||
<SubmitButton value="Submit" />
|
<SubmitButton value="Submit" />
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import DeleteUserButton from "./DeleteUserButton";
|
import DeleteUserButton from "./DeleteUserButton";
|
||||||
|
import EditUserButton from "./EditUserButton";
|
||||||
import type { User } from "../types/User";
|
import type { User } from "../types/User";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
entry: { loading: boolean, error: Error, user: User },
|
entry: { loading: boolean, error: Error, user: User },
|
||||||
deleteUser: string => void
|
deleteUser: string => void,
|
||||||
|
editUser: User => void
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class UserRow extends React.Component<Props> {
|
export default class UserRow extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { deleteUser } = this.props;
|
const { deleteUser, editUser } = this.props;
|
||||||
const user = this.props.entry.entry;
|
const user = this.props.entry.entry;
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
@@ -23,6 +25,9 @@ export default class UserRow extends React.Component<Props> {
|
|||||||
<td>
|
<td>
|
||||||
<DeleteUserButton user={user} deleteUser={deleteUser} />
|
<DeleteUserButton user={user} deleteUser={deleteUser} />
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<EditUserButton user={user} editUser={this.props.editUser} />
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import UserRow from "./UserRow";
|
import UserRow from "./UserRow";
|
||||||
|
import { editUser } from "../modules/users";
|
||||||
import type { User } from "../types/User";
|
import type { User } from "../types/User";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
entries: [{ loading: boolean, error: Error, user: User }],
|
entries: [{ loading: boolean, error: Error, user: User }],
|
||||||
deleteUser: string => void
|
deleteUser: string => void,
|
||||||
|
editUser: User => void
|
||||||
};
|
};
|
||||||
|
|
||||||
class UserTable extends React.Component<Props> {
|
class UserTable extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { deleteUser } = this.props;
|
const { deleteUser, editUser } = this.props;
|
||||||
const entries = this.props.entries;
|
const entries = this.props.entries;
|
||||||
return (
|
return (
|
||||||
<table>
|
<table>
|
||||||
@@ -25,7 +27,12 @@ class UserTable extends React.Component<Props> {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{entries.map((entry, index) => {
|
{entries.map((entry, index) => {
|
||||||
return (
|
return (
|
||||||
<UserRow key={index} entry={entry} deleteUser={deleteUser} />
|
<UserRow
|
||||||
|
key={index}
|
||||||
|
entry={entry}
|
||||||
|
deleteUser={deleteUser}
|
||||||
|
editUser={editUser}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { connect } from "react-redux";
|
|||||||
import {
|
import {
|
||||||
fetchUsers,
|
fetchUsers,
|
||||||
addUser,
|
addUser,
|
||||||
|
updateUser,
|
||||||
editUser,
|
editUser,
|
||||||
deleteUser,
|
deleteUser,
|
||||||
getUsersFromState
|
getUsersFromState
|
||||||
@@ -26,10 +27,12 @@ type Props = {
|
|||||||
fetchUsers: () => void,
|
fetchUsers: () => void,
|
||||||
deleteUser: string => void,
|
deleteUser: string => void,
|
||||||
addUser: User => void,
|
addUser: User => void,
|
||||||
editUser: User => void
|
updateUser: User => void,
|
||||||
|
editUser: User => void,
|
||||||
|
userToEdit: User
|
||||||
};
|
};
|
||||||
|
|
||||||
class Users extends React.Component<Props> {
|
class Users extends React.Component<Props, User> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.fetchUsers();
|
this.props.fetchUsers();
|
||||||
}
|
}
|
||||||
@@ -38,29 +41,43 @@ class Users extends React.Component<Props> {
|
|||||||
this.props.addUser(user);
|
this.props.addUser(user);
|
||||||
};
|
};
|
||||||
|
|
||||||
editUser = (user: User) => {
|
updateUser = (user: User) => {
|
||||||
this.props.editUser(user);
|
this.props.updateUser(user);
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: Props) {
|
||||||
|
if (prevProps.userToEdit !== this.props.userToEdit) {
|
||||||
|
this.setState(this.props.userToEdit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submitUser = (user: User) => {
|
||||||
|
if (user._links && user._links.update) {
|
||||||
|
this.updateUser(user);
|
||||||
|
} else {
|
||||||
|
this.addUser(user);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { userEntries, deleteUser } = this.props;
|
const { userEntries, deleteUser, editUser } = this.props;
|
||||||
const testUser: User = {
|
|
||||||
name: "user",
|
|
||||||
displayName: "user_display",
|
|
||||||
password: "pw",
|
|
||||||
mail: "mail@mail.de",
|
|
||||||
active: true,
|
|
||||||
admin: true
|
|
||||||
};
|
|
||||||
if (userEntries) {
|
if (userEntries) {
|
||||||
return (
|
return (
|
||||||
<section className="section">
|
<section className="section">
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<h1 className="title">SCM</h1>
|
<h1 className="title">SCM</h1>
|
||||||
<h2 className="subtitle">Users</h2>
|
<h2 className="subtitle">Users</h2>
|
||||||
<UserTable entries={userEntries} deleteUser={deleteUser} />
|
<UserTable
|
||||||
{/* <UserForm submitForm={this.submitForm} /> */}
|
entries={userEntries}
|
||||||
<UserForm submitForm={user => {}} user={testUser} />
|
deleteUser={deleteUser}
|
||||||
|
editUser={(user: User) => {
|
||||||
|
this.props.editUser(user);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<UserForm
|
||||||
|
submitForm={user => this.submitUser(user)}
|
||||||
|
user={this.props.userToEdit}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
@@ -72,11 +89,13 @@ class Users extends React.Component<Props> {
|
|||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
const userEntries = getUsersFromState(state);
|
const userEntries = getUsersFromState(state);
|
||||||
|
var userToEdit = state.users.editUser;
|
||||||
if (!userEntries) {
|
if (!userEntries) {
|
||||||
return {};
|
return { userToEdit };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
userEntries
|
userEntries,
|
||||||
|
userToEdit
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,11 +107,14 @@ const mapDispatchToProps = dispatch => {
|
|||||||
addUser: (user: User) => {
|
addUser: (user: User) => {
|
||||||
dispatch(addUser(user));
|
dispatch(addUser(user));
|
||||||
},
|
},
|
||||||
editUser: (user: User) => {
|
updateUser: (user: User) => {
|
||||||
dispatch(editUser(user));
|
dispatch(updateUser(user));
|
||||||
},
|
},
|
||||||
deleteUser: (link: string) => {
|
deleteUser: (link: string) => {
|
||||||
dispatch(deleteUser(link));
|
dispatch(deleteUser(link));
|
||||||
|
},
|
||||||
|
editUser: (user: User) => {
|
||||||
|
dispatch(editUser(user));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { apiClient, NOT_FOUND_ERROR } from "../../apiclient";
|
import { apiClient, NOT_FOUND_ERROR } from "../../apiclient";
|
||||||
import type { User } from "../types/User";
|
import type { User } from "../types/User";
|
||||||
import { ThunkDispatch } from "redux-thunk";
|
import { ThunkDispatch } from "redux-thunk";
|
||||||
|
import { Dispatch } from "redux";
|
||||||
|
|
||||||
export const FETCH_USERS = "scm/users/FETCH";
|
export const FETCH_USERS = "scm/users/FETCH";
|
||||||
export const FETCH_USERS_SUCCESS = "scm/users/FETCH_SUCCESS";
|
export const FETCH_USERS_SUCCESS = "scm/users/FETCH_SUCCESS";
|
||||||
@@ -13,8 +14,10 @@ export const ADD_USER_SUCCESS = "scm/users/ADD_SUCCESS";
|
|||||||
export const ADD_USER_FAILURE = "scm/users/ADD_FAILURE";
|
export const ADD_USER_FAILURE = "scm/users/ADD_FAILURE";
|
||||||
|
|
||||||
export const EDIT_USER = "scm/users/EDIT";
|
export const EDIT_USER = "scm/users/EDIT";
|
||||||
export const EDIT_USER_SUCCESS = "scm/users/EDIT_SUCCESS";
|
|
||||||
export const EDIT_USER_FAILURE = "scm/users/EDIT_FAILURE";
|
export const UPDATE_USER = "scm/users/UPDATE";
|
||||||
|
export const UPDATE_USER_SUCCESS = "scm/users/UPDATE_SUCCESS";
|
||||||
|
export const UPDATE_USER_FAILURE = "scm/users/UPDATE_FAILURE";
|
||||||
|
|
||||||
export const DELETE_USER = "scm/users/DELETE";
|
export const DELETE_USER = "scm/users/DELETE";
|
||||||
export const DELETE_USER_SUCCESS = "scm/users/DELETE_SUCCESS";
|
export const DELETE_USER_SUCCESS = "scm/users/DELETE_SUCCESS";
|
||||||
@@ -85,7 +88,7 @@ function requestAddUser(user: User) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function addUser(user: User) {
|
export function addUser(user: User) {
|
||||||
return function(dispatch: ThunkDispatch) {
|
return function(dispatch: Dispatch) {
|
||||||
dispatch(requestAddUser(user));
|
dispatch(requestAddUser(user));
|
||||||
return apiClient
|
return apiClient
|
||||||
.postWithContentType(USERS_URL, user, CONTENT_TYPE_USER)
|
.postWithContentType(USERS_URL, user, CONTENT_TYPE_USER)
|
||||||
@@ -111,9 +114,36 @@ function addUserFailure(user: User, err: Error) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestAddUser(user: User) {
|
function requestUpdateUser(user: User) {
|
||||||
return {
|
return {
|
||||||
type: ADD_USER,
|
type: UPDATE_USER,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateUser(user: User) {
|
||||||
|
return function(dispatch: Dispatch) {
|
||||||
|
dispatch(requestUpdateUser(user));
|
||||||
|
return apiClient
|
||||||
|
.putWithContentType(user._links.update.href, user, CONTENT_TYPE_USER)
|
||||||
|
.then(() => {
|
||||||
|
dispatch(updateUserSuccess());
|
||||||
|
dispatch(fetchUsers());
|
||||||
|
})
|
||||||
|
.catch(err => dispatch(updateUserFailure(user, err)));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUserSuccess() {
|
||||||
|
return {
|
||||||
|
type: UPDATE_USER_SUCCESS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUserFailure(user: User, error: Error) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_USER_FAILURE,
|
||||||
|
payload: error,
|
||||||
user
|
user
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -131,20 +161,6 @@ export function editUser(user: User) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function editUserSuccess() {
|
|
||||||
return {
|
|
||||||
type: ADD_USER_SUCCESS
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function addUserFailure(user: User, err: Error) {
|
|
||||||
return {
|
|
||||||
type: ADD_USER_FAILURE,
|
|
||||||
payload: err,
|
|
||||||
user
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function requestDeleteUser(url: string) {
|
function requestDeleteUser(url: string) {
|
||||||
return {
|
return {
|
||||||
type: DELETE_USER,
|
type: DELETE_USER,
|
||||||
@@ -215,6 +231,13 @@ function extractUsersByNames(
|
|||||||
return usersByNames;
|
return usersByNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function editUser(user: User) {
|
||||||
|
return {
|
||||||
|
type: EDIT_USER,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default function reducer(state: any = {}, action: any = {}) {
|
export default function reducer(state: any = {}, action: any = {}) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_USERS:
|
case FETCH_USERS:
|
||||||
@@ -253,7 +276,11 @@ export default function reducer(state: any = {}, action: any = {}) {
|
|||||||
error: action.payload,
|
error: action.payload,
|
||||||
loading: false
|
loading: false
|
||||||
};
|
};
|
||||||
|
case EDIT_USER:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
editUser: action.user
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user