Make functional AddUser/CreateGroup/EditUser

This commit is contained in:
Nathan Barber
2021-04-07 11:56:45 -04:00
parent dc4bbc01bb
commit 0f5e86ff06
14 changed files with 325 additions and 357 deletions

File diff suppressed because one or more lines are too long

View File

@@ -11,7 +11,7 @@ import { createBrowserHistory } from "history";
import ServerDashboard from "./components/ServerDashboard/ServerDashboard"; import ServerDashboard from "./components/ServerDashboard/ServerDashboard";
import Groups from "./components/Groups/Groups"; import Groups from "./components/Groups/Groups";
import GroupEdit from "./components/GroupEdit/GroupEdit"; import GroupEdit from "./components/GroupEdit/GroupEdit";
import CreateGroup from "./components/CreateGroup/CreateGroup" import CreateGroup from "./components/CreateGroup/CreateGroup";
import AddUser from "./components/AddUser/AddUser"; import AddUser from "./components/AddUser/AddUser";
import EditUser from "./components/EditUser/EditUser"; import EditUser from "./components/EditUser/EditUser";

View File

@@ -1,7 +1,7 @@
import { connect } from "react-redux"; import { connect } from "react-redux";
import { compose, withProps } from "recompose"; import { compose, withProps } from "recompose";
import { jhapiRequest } from "../../util/jhapiUtil"; import { jhapiRequest } from "../../util/jhapiUtil";
import { AddUser } from "./AddUser.pre"; import AddUser from "./AddUser.pre";
const withUserAPI = withProps((props) => ({ const withUserAPI = withProps((props) => ({
addUsers: (usernames, admin) => addUsers: (usernames, admin) =>

View File

@@ -1,116 +1,101 @@
import React, { Component } from "react"; import React, { Component, useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
export class AddUser extends Component { const AddUser = (props) => {
static get propTypes() { var [users, setUsers] = useState([]),
return { [admin, setAdmin] = useState(false);
addUsers: PropTypes.func,
failRegexEvent: PropTypes.func,
refreshUserData: PropTypes.func,
dispatch: PropTypes.func,
history: PropTypes.shape({
push: PropTypes.func,
}),
};
}
constructor(props) { var { addUsers, failRegexEvent, refreshUserData, history } = props;
super(props);
this.state = {
users: [],
admin: false,
};
}
render() { return (
var { addUsers, failRegexEvent, refreshUserData, dispatch } = this.props; <>
<div className="container">
return ( <div className="row">
<> <div className="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
<div className="container"> <div className="panel panel-default">
<div className="row"> <div className="panel-heading">
<div className="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2"> <h4>Add Users</h4>
<div className="panel panel-default"> </div>
<div className="panel-heading"> <div className="panel-body">
<h4>Add Users</h4> <form>
</div> <div className="form-group">
<div className="panel-body"> <textarea
<form> className="form-control"
<div className="form-group"> id="add-user-textarea"
<textarea rows="3"
className="form-control" placeholder="usernames separated by line"
id="add-user-textarea" onBlur={(e) => {
rows="3" let split_users = e.target.value.split("\n");
placeholder="usernames separated by line" setUsers(split_users);
onBlur={(e) => { }}
let split_users = e.target.value.split("\n"); ></textarea>
this.setState( <br></br>
Object.assign({}, this.state, { <input
users: split_users, className="form-check-input"
}) type="checkbox"
); value=""
}} id="admin-check"
></textarea> onChange={(e) =>
<br></br> // this.setState(
<input // Object.assign({}, this.state, {
className="form-check-input" // admin: e.target.checked,
type="checkbox" // })
value="" // )
id="admin-check" setAdmin(e.target.checked)
onChange={(e) =>
this.setState(
Object.assign({}, this.state, {
admin: e.target.checked,
})
)
}
/>
<span> </span>
<label className="form-check-label">Admin</label>
</div>
</form>
</div>
<div className="panel-footer">
<button id="return" className="btn btn-light">
<Link to="/">Back</Link>
</button>
<span> </span>
<button
id="submit"
className="btn btn-primary"
onClick={() => {
let filtered_users = this.state.users.filter(
(e) =>
e.length > 2 &&
/[!@#$%^&*(),.?":{}|<>]/g.test(e) == false
);
if (filtered_users.length < this.state.users.length) {
let removed_users = this.state.users.filter(
(e) => !filtered_users.includes(e)
);
this.setState(
Object.assign({}, this.state, {
users: filtered_users,
})
);
failRegexEvent();
} }
/>
<span> </span>
<label className="form-check-label">Admin</label>
</div>
</form>
</div>
<div className="panel-footer">
<button id="return" className="btn btn-light">
<Link to="/">Back</Link>
</button>
<span> </span>
<button
id="submit"
className="btn btn-primary"
onClick={() => {
let filtered_users = users.filter(
(e) =>
e.length > 2 &&
/[!@#$%^&*(),.?":{}|<>]/g.test(e) == false
);
if (filtered_users.length < users.length) {
let removed_users = users.filter(
(e) => !filtered_users.includes(e)
);
setUsers(filtered_users);
failRegexEvent();
}
addUsers(filtered_users, this.state.admin) addUsers(filtered_users, admin)
.then(() => refreshUserData()) .then(() => refreshUserData())
.then(() => this.props.history.push("/")) .then(() => history.push("/"))
.catch((err) => console.log(err)); .catch((err) => console.log(err));
}} }}
> >
Add Users Add Users
</button> </button>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</> </div>
); </>
} );
} };
AddUser.propTypes = {
addUsers: PropTypes.func,
failRegexEvent: PropTypes.func,
refreshUserData: PropTypes.func,
history: PropTypes.shape({
push: PropTypes.func,
}),
};
export default AddUser;

View File

@@ -1,7 +1,7 @@
import { connect } from "react-redux"; import { connect } from "react-redux";
import { compose, withProps } from "recompose"; import { compose, withProps } from "recompose";
import { jhapiRequest } from "../../util/jhapiUtil"; import { jhapiRequest } from "../../util/jhapiUtil";
import { CreateGroup } from "./CreateGroup.pre"; import CreateGroup from "./CreateGroup.pre";
const withUserAPI = withProps((props) => ({ const withUserAPI = withProps((props) => ({
createGroup: (groupName) => jhapiRequest("/groups/" + groupName, "POST"), createGroup: (groupName) => jhapiRequest("/groups/" + groupName, "POST"),

View File

@@ -1,77 +1,69 @@
import React, { Component } from "react"; import React, { Component, useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Multiselect from "../Multiselect/Multiselect";
export class CreateGroup extends Component { const CreateGroup = (props) => {
static get propTypes() { var [groupName, setGroupName] = useState("");
return {
createGroup: PropTypes.func,
refreshGroupsData: PropTypes.func,
failRegexEvent: PropTypes.func,
history: PropTypes.shape({
push: PropTypes.func,
}),
};
}
constructor(props) { var { createGroup, refreshGroupsData, history } = props;
super(props);
this.state = {
groupName: "",
};
}
render() { return (
var { createGroup, refreshGroupsData } = this.props; <>
<div className="container">
return ( <div className="row">
<> <div className="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
<div className="container"> <div className="panel panel-default">
<div className="row"> <div className="panel-heading">
<div className="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2"> <h4>Create Group</h4>
<div className="panel panel-default"> </div>
<div className="panel-heading"> <div className="panel-body">
<h4>Create Group</h4> <div className="input-group">
</div> <input
<div className="panel-body"> className="group-name-input"
<div className="input-group"> type="text"
<input value={groupName}
className="group-name-input" id="group-name"
type="text" placeholder="group name..."
value={this.state.groupName} onChange={(e) => {
id="group-name" setGroupName(e.target.value);
placeholder="group name..."
onChange={(e) => {
this.setState({ groupName: e.target.value });
}}
></input>
</div>
</div>
<div className="panel-footer">
<button id="return" className="btn btn-light">
<Link to="/">Back</Link>
</button>
<span> </span>
<button
id="submit"
className="btn btn-primary"
onClick={() => {
let groupName = this.state.groupName;
createGroup(groupName)
.then(refreshGroupsData())
.then(this.props.history.push("/groups"))
.catch((err) => console.log(err));
}} }}
> ></input>
Add Users
</button>
</div> </div>
</div> </div>
<div className="panel-footer">
<button id="return" className="btn btn-light">
<Link to="/">Back</Link>
</button>
<span> </span>
<button
id="submit"
className="btn btn-primary"
onClick={() => {
let groupName = groupName;
createGroup(groupName)
.then(refreshGroupsData())
.then(history.push("/groups"))
.catch((err) => console.log(err));
}}
>
Add Users
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
</> </div>
); </>
} );
} };
CreateGroup.propTypes = {
createGroup: PropTypes.func,
refreshGroupsData: PropTypes.func,
failRegexEvent: PropTypes.func,
history: PropTypes.shape({
push: PropTypes.func,
}),
};
export default CreateGroup;

View File

@@ -1,7 +1,7 @@
import { connect } from "react-redux"; import { connect } from "react-redux";
import { compose, withProps } from "recompose"; import { compose, withProps } from "recompose";
import { jhapiRequest } from "../../util/jhapiUtil"; import { jhapiRequest } from "../../util/jhapiUtil";
import { EditUser } from "./EditUser.pre"; import EditUser from "./EditUser.pre";
const withUserAPI = withProps((props) => ({ const withUserAPI = withProps((props) => ({
editUser: (username, updated_username, admin) => editUser: (username, updated_username, admin) =>

View File

@@ -1,152 +1,130 @@
import React, { Component } from "react"; import React, { Component, useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
export class EditUser extends Component { const EditUser = (props) => {
static get propTypes() { var {
return { editUser,
location: PropTypes.shape({ deleteUser,
state: PropTypes.shape({ failRegexEvent,
username: PropTypes.string, refreshUserData,
has_admin: PropTypes.bool, history,
}), } = props;
}),
history: PropTypes.shape({ if (props.location.state == undefined) {
push: PropTypes.func, props.history.push("/");
}), return <></>;
editUser: PropTypes.func,
deleteUser: PropTypes.func,
failRegexEvent: PropTypes.func,
refreshUserData: PropTypes.func,
};
} }
constructor(props) { var { username, has_admin } = props.location.state;
super(props);
this.state = {
updated_username: null,
admin: null,
};
}
render() { var [updatedUsername, setUpdatedUsername] = useState(""),
if (this.props.location.state == undefined) { [admin, setAdmin] = useState(has_admin);
this.props.history.push("/");
return <></>;
}
var { username, has_admin } = this.props.location.state; return (
<>
var { editUser, deleteUser, failRegexEvent, refreshUserData } = this.props; <div className="container">
<div className="row">
return ( <div className="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
<> <div className="panel panel-default">
<div className="container"> <div className="panel-heading">
<div className="row"> <h4>Editing user {username}</h4>
<div className="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2"> </div>
<div className="panel panel-default"> <div className="panel-body">
<div className="panel-heading"> <form>
<h4>Editing user {username}</h4> <div className="form-group">
</div> <textarea
<div className="panel-body"> className="form-control"
<form> id="exampleFormControlTextarea1"
<div className="form-group"> rows="3"
<textarea placeholder="updated username"
className="form-control" onBlur={(e) => {
id="exampleFormControlTextarea1" setUpdatedUsername(e.target.value);
rows="3" }}
placeholder="updated username" ></textarea>
onKeyDown={(e) => { <br></br>
this.setState( <input
Object.assign({}, this.state, { className="form-check-input"
updated_username: e.target.value, checked={admin}
}) type="checkbox"
); id="admin-check"
}} onChange={(e) => setAdmin(!admin)}
></textarea> />
<br></br> <span> </span>
<input <label className="form-check-label">Admin</label>
className="form-check-input" <br></br>
checked={has_admin ? true : false} <button
type="checkbox" id="delete-user"
value="" className="btn btn-danger btn-sm"
id="admin-check" onClick={() => {
onChange={(e) => deleteUser(username)
this.setState(
Object.assign({}, this.state, {
admin: e.target.checked,
})
)
}
/>
<span> </span>
<label className="form-check-label">Admin</label>
<br></br>
<button
id="delete-user"
className="btn btn-danger btn-sm"
onClick={() => {
deleteUser(username)
.then((data) => {
this.props.history.push("/");
refreshUserData();
})
.catch((err) => console.log(err));
}}
>
Delete user
</button>
</div>
</form>
</div>
<div className="panel-footer">
<button className="btn btn-light">
<Link to="/">Back</Link>
</button>
<span> </span>
<button
id="submit"
className="btn btn-primary"
onClick={() => {
let updated_username = this.state.updated_username,
admin = this.state.admin;
if (updated_username == null && admin == null) return;
if (
updated_username.length > 2 &&
/[!@#$%^&*(),.?":{}|<>]/g.test(updated_username) ==
false
) {
editUser(
username,
updated_username != null
? updated_username
: username,
admin != null ? admin : has_admin
)
.then((data) => { .then((data) => {
this.props.history.push("/"); history.push("/");
refreshUserData(); refreshUserData();
}) })
.catch((err) => {}); .catch((err) => console.log(err));
} else { }}
this.setState( >
Object.assign({}, this.state, { Delete user
updated_username: "", </button>
}) </div>
); </form>
failRegexEvent(); </div>
} <div className="panel-footer">
}} <button className="btn btn-light">
> <Link to="/">Back</Link>
Apply </button>
</button> <span> </span>
</div> <button
id="submit"
className="btn btn-primary"
onClick={() => {
if (updatedUsername == "" && admin == has_admin) return;
if (
updatedUsername.length > 2 &&
/[!@#$%^&*(),.?":{}|<>]/g.test(updatedUsername) == false
) {
editUser(
username,
updatedUsername != "" ? updatedUsername : username,
admin
)
.then((data) => {
history.push("/");
refreshUserData();
})
.catch((err) => {});
} else {
setUpdatedUsername(null);
failRegexEvent();
}
}}
>
Apply
</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</> </div>
); </>
} );
} };
EditUser.propTypes = {
location: PropTypes.shape({
state: PropTypes.shape({
username: PropTypes.string,
has_admin: PropTypes.bool,
}),
}),
history: PropTypes.shape({
push: PropTypes.func,
}),
editUser: PropTypes.func,
deleteUser: PropTypes.func,
failRegexEvent: PropTypes.func,
refreshUserData: PropTypes.func,
};
export default EditUser;

View File

@@ -8,8 +8,7 @@ const withGroupsAPI = withProps((props) => ({
jhapiRequest("/groups/" + groupname + "/users", "POST", { users }), jhapiRequest("/groups/" + groupname + "/users", "POST", { users }),
removeFromGroup: (users, groupname) => removeFromGroup: (users, groupname) =>
jhapiRequest("/groups/" + groupname + "/users", "DELETE", { users }), jhapiRequest("/groups/" + groupname + "/users", "DELETE", { users }),
deleteGroup: (name) => deleteGroup: (name) => jhapiRequest("/groups/" + name, "DELETE"),
jhapiRequest("/groups/" + name, "DELETE"),
refreshGroupsData: () => refreshGroupsData: () =>
jhapiRequest("/groups", "GET") jhapiRequest("/groups", "GET")
.then((data) => data.json()) .then((data) => data.json())

View File

@@ -18,7 +18,7 @@ export class GroupEdit extends Component {
}), }),
addToGroup: PropTypes.func, addToGroup: PropTypes.func,
removeFromGroup: PropTypes.func, removeFromGroup: PropTypes.func,
deleteGroup: PropTypes.func deleteGroup: PropTypes.func,
}; };
} }
@@ -40,7 +40,12 @@ export class GroupEdit extends Component {
var { group_data, user_data, callback } = this.props.location.state; var { group_data, user_data, callback } = this.props.location.state;
var { addToGroup, removeFromGroup, deleteGroup, refreshGroupsData } = this.props; var {
addToGroup,
removeFromGroup,
deleteGroup,
refreshGroupsData,
} = this.props;
if (!(group_data && user_data)) return <div></div>; if (!(group_data && user_data)) return <div></div>;
@@ -104,13 +109,19 @@ export class GroupEdit extends Component {
> >
Apply Apply
</button> </button>
<button className="btn btn-danger" style={{ float: "right" }} onClick={() => { <button
var groupName = group_data.name className="btn btn-danger"
deleteGroup(groupName) style={{ float: "right" }}
.then(refreshGroupsData()) onClick={() => {
.then(this.props.history.push("/groups")) var groupName = group_data.name;
.catch(err => console.log(err)) deleteGroup(groupName)
}}>Delete Group</button> .then(refreshGroupsData())
.then(this.props.history.push("/groups"))
.catch((err) => console.log(err));
}}
>
Delete Group
</button>
<br></br> <br></br>
<br></br> <br></br>
</div> </div>

View File

@@ -21,7 +21,7 @@ const withGroupsAPI = withProps((props) => ({
jhapiRequest("/groups/" + name + "/users", "DELETE", { jhapiRequest("/groups/" + name + "/users", "DELETE", {
body: { users: removed_users }, body: { users: removed_users },
json: true, json: true,
}) }),
})); }));
export default compose( export default compose(

View File

@@ -69,9 +69,12 @@ export class Groups extends Component {
<button className="btn btn-light adjacent-span-spacing"> <button className="btn btn-light adjacent-span-spacing">
<Link to="/">Back</Link> <Link to="/">Back</Link>
</button> </button>
<button className="btn btn-primary adjacent-span-spacing" onClick={() => { <button
this.props.history.push("/create-group") className="btn btn-primary adjacent-span-spacing"
}}> onClick={() => {
this.props.history.push("/create-group");
}}
>
New Group New Group
</button> </button>
</div> </div>

View File

@@ -1 +1 @@
16381 17503

File diff suppressed because one or more lines are too long