From a03b0e0e206a65fe58040ef681da88bbcf962673 Mon Sep 17 00:00:00 2001 From: mshriver Date: Mon, 17 Feb 2025 09:07:06 -0500 Subject: [PATCH] Convert UserEdit to functional --- frontend/src/pages/admin/user-edit.js | 515 +++++++++++--------------- 1 file changed, 226 insertions(+), 289 deletions(-) diff --git a/frontend/src/pages/admin/user-edit.js b/frontend/src/pages/admin/user-edit.js index f1f21223..04386fc0 100644 --- a/frontend/src/pages/admin/user-edit.js +++ b/frontend/src/pages/admin/user-edit.js @@ -1,5 +1,4 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React, { useState, useEffect } from 'react'; import { ActionGroup, @@ -34,322 +33,260 @@ import { TimesIcon } from '@patternfly/react-icons'; import { HttpClient } from '../../services/http'; import { Settings } from '../../settings'; import { projectToOption } from '../../utilities'; +import { useLocation, useNavigate, useParams } from 'react-router-dom'; +import PropTypes from 'prop-types'; -export class UserEdit extends React.Component { - static propTypes = { - params: PropTypes.object, - location: PropTypes.object, - navigate: PropTypes.func, - }; +const UserEdit = (props) => { + const {id} = props; - constructor (props) { - super(props); - this.state = { - id: props.params.id, - user: null, - filteredProjects: [], - projects: [], - userProjects: [], - isProjectsOpen: false, - inputValue: '', - }; - } + const params = useParams(); + const navigate = useNavigate(); + const location = useLocation(); - onUserNameChanged = (value) => { - const { user } = this.state; - user.name = value; - this.setState({user}); - }; + //const [id, setId] = useState(); + const [user, setUser] = useState(); + const [filteredProjects, setFilteredProjects] = useState([]); + const [projects, setProjects] = useState([]); + const [userProjects, setUserProjects] = useState([]); + const [isProjectsOpen, setIsProjectsOpen] = useState(false); + const [inputValue, setInputValue] = useState(''); - onUserEmailChanged = (value) => { - const { user } = this.state; - user.email = value; - this.setState({user}); - }; - - onIsActiveToggle = (checked) => { - const { user } = this.state; - user.is_active = checked; - this.setState({user}); - }; - - onIsAdminToggle = (checked) => { - const { user } = this.state; - user.is_superadmin = checked; - this.setState({user}); - }; - - onSubmitClick = () => { - const { user, userProjects } = this.state; - user.projects = userProjects.map((projectOption) => projectOption.project); - this.saveUser(user.id, user) - .then(() => this.props.navigate(-1)) - .catch((error) => console.log(error)); - }; - - onProjectsToggle = () => { - this.setState({isProjectsOpen: !this.state.isProjectsOpen}); + const onSubmitClick = () => { + userData = {...user} + userData['projects'] = userProjects.map((projectOption) => projectOption.project); + return HttpClient.put([Settings.serverUrl, 'admin', 'user', userId], {}, userData) + .then(response => HttpClient.handleResponse(response, 'response')) + .catch(error => console.error('Error committing user update')) }; - onProjectsSelect = (_event, value) => { - const { userProjects } = this.state; + const onProjectsSelect = (_event, value) => { if (userProjects.filter(item => item.compareTo(value)).length !== 0) { - this.setState( - prevState => ({userProjects: prevState.userProjects.filter(item => !item.compareTo(value))}) - ); + setUserProjects(userProjects.filter(item => !item.compareTo(value))) } else { - this.setState( - prevState => ({userProjects: [...prevState.userProjects, value]}) - ); + setUserProjects([...userProjects, value]) } }; - onProjectsClear = () => { - this.setState({ - userProjects: [], - isProjectsOpen: false, - inputValue: '' - }); + const onProjectsClear = () => { + setUserProjects([]); + setIsProjectsOpen(false); + setInputValue(''); }; - getUser (userId) { - HttpClient.get([Settings.serverUrl, 'admin', 'user', userId]) - .then(response => { - response = HttpClient.handleResponse(response, 'response'); - return response.json(); + useEffect(() => { + // get user once + HttpClient.get([Settings.serverUrl, 'admin', 'user', id]) + .then(response => HttpClient.handleResponse(response, 'response')) + .then(data => { + setUser(data); + setUserProjects(data.projects.map(projectToOption)); }) - .then(user => this.setState({user: user, userProjects: user.projects.map(projectToOption)})) .catch(error => console.error(error)); - } + }, [id]); - getProjects () { + useEffect(() => { + // fetch projects once HttpClient.get([Settings.serverUrl, 'admin', 'project']) - .then(response => { - response = HttpClient.handleResponse(response, 'response'); - return response.json(); + .then(response => HttpClient.handleResponse(response, 'response')) + .then(data => { + setProjects(data.projects); + setFilteredProjects(data.projects); }) - .then(data => this.setState({projects: data.projects, filteredProjects: data.projects})) .catch(error => console.error(error)); - } + }, []); - saveUser (userId, user) { - return HttpClient.put([Settings.serverUrl, 'admin', 'user', userId], {}, user) - .then(response => HttpClient.handleResponse(response, 'response')) - .then(response => response.json()); - } - - goBack = () => { - this.props.navigate(-1); - }; - - onTextInputChange = (_event, value) => { - this.setState({inputValue: value}); - }; - - componentDidMount () { - this.getUser(this.state.id); - this.getProjects(); - } - - componentDidUpdate (prevProps, prevState) { - if ( - prevState.inputValue !== this.state.inputValue - ) { - let newSelectOptions = this.state.projects; - if (this.state.inputValue) { - newSelectOptions = this.state.projects.filter(menuItem => - String(menuItem.title).toLowerCase().includes(this.state.inputValue.toLowerCase()) - ); - - if (newSelectOptions.length === 0) { - newSelectOptions = [{ - isDisabled: true, - value: {}, - title: `No results found for "${this.state.inputValue}"`, - }]; - } + useEffect(() => { + // handle input value changing for project filter + if (inputValue) { + let newProjectOptions = projects.filter(menuItem => + String(menuItem.title).toLowerCase().includes(inputValue.toLowerCase()) + ); - if (!this.state.isProjectsOpen) { - this.setState({ isProjectsOpen: true }); - } + if (newProjectOptions.length === 0) { + newProjectOptions = [{ + isDisabled: true, + value: {}, + title: `No results found for "${inputValue}"`, + }]; } + setFilteredProjects(newProjectOptions); - this.setState({ - filteredProjects: newSelectOptions, - }); } - } - render () { - const { projects, inputValue, filteredProjects, user, userProjects } = this.state; + }, [inputValue, projects]); - const toggle = toggleRef => ( - - - - - {userProjects.map((userProject, index) => ( - { - ev.stopPropagation(); - this.onProjectsSelect(ev, userProject); - }} - > - {userProject.project.title} - - ))} - - - - {(userProjects.length > 0 || inputValue !== '') && ( - - )} - - - - ); + {userProject.project.title} + + ))} + + + + {(userProjects.length > 0 || inputValue !== '') && ( + + )} + + + + ); - return ( - - - - Users / {user && user.name} {' '} - {user && user.is_superadmin && - <Label className="super-admin-label" variant="outline" color="blue">Administrator</Label> - } - - - - {!user && } - {user && - - -
- - this.onUserNameChanged(value)} - /> - - - The user's name - - - - - this.onUserEmailChanged(value)} - /> - - - The user's e-mail address - - - - - this.onIsActiveToggle(checked)} - /> - this.onIsAdminToggle(checked)} - /> - - - - - - The projects to which a user has access - - - - - - - -
-
-
+ return ( + + + + Users / {user?.name} {' '} + {user?.is_superadmin && + <Label className="super-admin-label" variant="outline" color="blue">Administrator</Label> } - </PageSection> - </React.Fragment> - ); - } -} + + + + {!user && } + {user && + + +
+ + setUser({...user, 'name': value})} + /> + + + The user's name + + + + + setUser({...user, 'email': value})} + /> + + + The user's e-mail address + + + + + setUser({...user, 'is_active': checked})} + /> + setUser({...user, 'is_superadmin': checked})} + /> + + + + + + The projects to which a user has access + + + + + + + +
+
+
+ } +
+
+ ); +}; + +UserEdit.propTypes = { + id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), +}; + +export default UserEdit;