From efbb07105227b61dd157b041d2bfb9942f1428c8 Mon Sep 17 00:00:00 2001 From: Peterson Rodrigues dos Santos Date: Thu, 23 May 2024 18:00:20 -0300 Subject: [PATCH 01/11] Peterson_Implement_toast_when_user_is_already_in_a_team --- .../TeamsAndProjects/AddTeamPopup.jsx | 78 ++++++++++++------- .../UserProfile/TeamsAndProjects/TeamsTab.jsx | 13 ++-- .../__tests__/AddTeamPopup.test.js | 3 +- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx index 59acdbf64c..9413bd11c4 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx @@ -21,6 +21,7 @@ const AddTeamPopup = React.memo(props => { const [newTeamName, setNewTeamName] = useState(''); const [newTeamIsActive, setNewTeamIsActive] = useState(true); const [isDuplicateTeam, setDuplicateTeam] = useState(false); + const [isNotDisplayToast, setIsNotDisplayToast] = useState(false); const onAssignTeam = () => { if (!searchText) { @@ -28,7 +29,24 @@ const AddTeamPopup = React.memo(props => { onValidation(false); return; } - if (selectedTeam && !props.userTeamsById.some(x => x._id === selectedTeam._id)) { + + isNotDisplayToast && toast.warn('Please wait for the team to be created to add your user.'); + + if (selectedTeam && selectedTeam.members.length > 0 && !isNotDisplayToast) { + const userId = props.userProfile._id; + const usersTeam = selectedTeam.members.map(item => item.userId); + const userIsAlreadyInATeam = usersTeam.includes(userId); + userIsAlreadyInATeam && + toast.error( + 'Your user has been found in this team. Please select another team to add your user.', + ); + } + + if ( + selectedTeam && + !props.userTeamsById.some(x => x._id === selectedTeam._id) && + !isNotDisplayToast + ) { props.onSelectAssignTeam(selectedTeam); toast.success('Team assigned successfully'); // toast notification onSelectTeam(undefined); @@ -45,30 +63,34 @@ const AddTeamPopup = React.memo(props => { const onCreateTeam = async () => { if (newTeamName !== '') { + setIsNotDisplayToast(true); const response = await dispatch(postNewTeam(newTeamName, newTeamIsActive)); - - if (response.status === 200) { - toast.success('Team created successfully'); - setNewTeamName(''); - setNewTeamIsActive(true); - setDuplicateTeam(false); - - // Get updated teams list and select the new team - await dispatch(getAllUserTeams()); - const newTeam = response.data; // Assuming response contains the new team data - onSelectTeam(newTeam); - setSearchText(newTeam.teamName); // Update search text to reflect new team name - - } else if (response.status === 400) { - setDuplicateTeam(true); - } else { - toast.error('Error occurred while creating team'); + try { + if (response.status === 200) { + toast.success('Team created successfully'); + setNewTeamName(''); + setNewTeamIsActive(true); + setDuplicateTeam(false); + + // Get updated teams list and select the new team + await dispatch(getAllUserTeams()); + const newTeam = response.data; // Assuming response contains the new team data + onSelectTeam(newTeam); + setSearchText(newTeam.teamName); // Update search text to reflect new team name + } + } catch (error) { + if (response.status === 400) { + setDuplicateTeam(true); + } else { + toast.error('Error occurred while creating team'); + } + } finally { + setIsNotDisplayToast(false); } } else { onNewTeamValidation(false); } }; - useEffect(() => { onValidation(true); @@ -83,7 +105,7 @@ const AddTeamPopup = React.memo(props => { Add Team - +
{ onCreateNewTeam={onCreateTeam} selectedTeam={selectedTeam} searchText={searchText} - setNewTeamName={setNewTeamName} + setNewTeamName={setNewTeamName} newTeamName={newTeamName} - setSearchText={setSearchText} // Added setSearchText prop + setSearchText={setSearchText} // Added setSearchText prop />
- {!isValidTeam && searchText && !selectedTeam && ( + {!isValidTeam && searchText && !selectedTeam && ( Oops, this team does not exist! Create it if you want it. - )} + )} {!isValidTeam && !searchText && ( Hey, You need to pick a team first! )} - {!isValidNewTeam && !isDuplicateTeam ? Please enter a team name. : null} - {isDuplicateTeam && ( - A team with this name already exists - )} + {!isValidNewTeam && !isDuplicateTeam ? ( + Please enter a team name. + ) : null} + {isDuplicateTeam && A team with this name already exists}
- {!isValidTeam && searchText && !selectedTeam && ( + {!isValidTeam && searchText && isNotDisplayAlert && !selectedTeam && ( Oops, this team does not exist! Create it if you want it. )} + {!isValidTeam && !searchText && ( Hey, You need to pick a team first! )} + {!isValidNewTeam && !isDuplicateTeam ? ( Please enter a team name. ) : null} diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx index 78845c0bdd..9238361e68 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx @@ -6,9 +6,9 @@ const AddTeamsAutoComplete = React.memo(props => { const [isOpen, toggle] = React.useState(false); React.useEffect(() => { - if (!props.selectedTeam) props.setSearchText(''); + if (!props.selectedTeam && props.setIsNotDisplayAlert) props.setSearchText(''); else props.setSearchText(props.selectedTeam.teamName); - }, [props.selectedTeam, props.setSearchText]); + }, [props.selectedTeam, props.setSearchText, props.setIsNotDisplayAlert]); return ( { value={props.searchText} autoFocus={true} onChange={e => { + props.setAutoComplete(1); props.setSearchText(e.target.value); props.setNewTeamName(e.target.value); toggle(true); @@ -48,7 +49,6 @@ const AddTeamsAutoComplete = React.memo(props => {
{ props.setSearchText(item.teamName); toggle(false); @@ -59,7 +59,6 @@ const AddTeamsAutoComplete = React.memo(props => {
))} - {props.teamsData.allTeams.every( team => team.teamName.toLowerCase() !== props.searchText.toLowerCase(), ) && ( @@ -73,8 +72,6 @@ const AddTeamsAutoComplete = React.memo(props => { Create new team: {props.searchText} )} - - ) : ( <> From b0553285f8c95fff7d153fdee4def680acdb14c0 Mon Sep 17 00:00:00 2001 From: Peterson Rodrigues dos Santos Date: Wed, 12 Jun 2024 17:18:06 -0300 Subject: [PATCH 04/11] Peterson_Implement_toast_when_user_is_already_in_a_team --- .../TeamsAndProjects/AddTeamPopup.jsx | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx index fafb079d39..3bf2b817e7 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx @@ -1,14 +1,14 @@ import React, { useEffect, useState } from 'react'; -import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Alert } from 'reactstrap'; +import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Alert, Spinner } from 'reactstrap'; import AddTeamsAutoComplete from './AddTeamsAutoComplete'; import { useDispatch } from 'react-redux'; import { toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; -import '../../Header/DarkMode.css' +import '../../Header/DarkMode.css'; import { postNewTeam, getAllUserTeams } from '../../../../src/actions/allTeamsAction'; const AddTeamPopup = React.memo(props => { - const {darkMode} = props; + const { darkMode } = props; const dispatch = useDispatch(); const closePopup = () => { @@ -24,9 +24,9 @@ const AddTeamPopup = React.memo(props => { const [newTeamName, setNewTeamName] = useState(''); const [newTeamIsActive, setNewTeamIsActive] = useState(true); const [isDuplicateTeam, setDuplicateTeam] = useState(false); - const [isNotDisplayToast, setIsNotDisplayToast] = useState(false); const [isNotDisplayAlert, setIsNotDisplayAlert] = useState(false); const [autoComplete, setAutoComplete] = useState(null); + const [isloading, setIsLoading] = useState(false); const format = result => result @@ -54,7 +54,6 @@ const AddTeamPopup = React.memo(props => { const condition = { TEAM_NAME: autoComplete === 0, obj: autoComplete === 1, - isNotDisplayToast: isNotDisplayToast, selectedTeam: selectedTeam, }; @@ -63,8 +62,6 @@ const AddTeamPopup = React.memo(props => { return; } - isNotDisplayToast && toast.warn('Please wait for the team to be created to add your user.'); - if (condition && processEnvNodeEnv) { const userId = props.userProfile._id; @@ -88,6 +85,8 @@ const AddTeamPopup = React.memo(props => { if (condition && some) { props.onSelectAssignTeam(condition.TEAM_NAME ? selectedTeam : condition.obj ? result : null); + setSearchText(''); + onValidation(true); toast.success('Team assigned successfully'); //toast notification } else { // when the user typed something but didn't select a team @@ -104,17 +103,17 @@ const AddTeamPopup = React.memo(props => { const onCreateTeam = async () => { if (newTeamName !== '') { - setIsNotDisplayToast(true); + setIsLoading(true); const response = await dispatch(postNewTeam(newTeamName, newTeamIsActive)); try { if (response.status === 200) { - toast.success('Team created successfully'); setNewTeamName(''); setNewTeamIsActive(true); setDuplicateTeam(false); // Get updated teams list and select the new team await dispatch(getAllUserTeams()); + toast.success('Team created successfully'); const newTeam = response.data; // Assuming response contains the new team data onSelectTeam(newTeam); setSearchText(newTeam.teamName); // Update search text to reflect new team name @@ -122,11 +121,12 @@ const AddTeamPopup = React.memo(props => { } catch (error) { if (response.status === 400) { setDuplicateTeam(true); + setIsLoading(false); } else { toast.error('Error occurred while creating team'); } } finally { - setIsNotDisplayToast(false); + setIsLoading(false); } } else { onNewTeamValidation(false); @@ -143,10 +143,19 @@ const AddTeamPopup = React.memo(props => { }, [newTeamName, newTeamIsActive, dispatch]); return ( - - Add Team + + + Add Team + - +
{ onValidation(false); } }} + disabled={isloading} > - Confirm + {isloading ? : 'Confirm'}
{!isValidTeam && searchText && isNotDisplayAlert && !selectedTeam && ( From bcef66c44d57d4d071dc9caa388e9fd6c3446cc1 Mon Sep 17 00:00:00 2001 From: Peterson Rodrigues dos Santos Date: Wed, 12 Jun 2024 17:47:02 -0300 Subject: [PATCH 05/11] Peterson_Implement_toast_when_user_is_already_in_a_team --- src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx index 3bf2b817e7..4dd4a51116 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx @@ -35,8 +35,8 @@ const AddTeamPopup = React.memo(props => { .replace(/\s+/g, ''); const IfTheUserNotSelectedSuggestionAutoComplete = () => { - const filterTeamData = props.teamsData.allTeams.filter(item => - format(item.teamName).includes(format(searchText)), + const filterTeamData = props.teamsData.allTeams.filter( + item => format(item.teamName) === format(searchText), ); if (filterTeamData.length > 0) { From 7477bb4ca700a67e7e035c43ad1e275c32e04a56 Mon Sep 17 00:00:00 2001 From: Peterson Rodrigues dos Santos Date: Fri, 14 Jun 2024 12:25:02 -0300 Subject: [PATCH 06/11] Peterson_Implement_toast_when_user_is_already_in_a_team --- .../TeamsAndProjects/AddTeamPopup.jsx | 23 ++++--------------- .../__test__/WeeklySummary.test.js | 2 +- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx index 4dd4a51116..61a1c36445 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx @@ -50,33 +50,17 @@ const AddTeamPopup = React.memo(props => { }; const onAssignTeam = result => { - const processEnvNodeEnv = process.env.NODE_ENV !== 'test'; const condition = { TEAM_NAME: autoComplete === 0, obj: autoComplete === 1, selectedTeam: selectedTeam, + result: result, }; if (!searchText) { onValidation(false); return; } - - if (condition && processEnvNodeEnv) { - const userId = props.userProfile._id; - - const usersTeam = condition.obj - ? result.members.map(item => item.userId) - : condition.TEAM_NAME - ? selectedTeam.members.map(item => item.userId) - : null; - - const userIsAlreadyInATeam = usersTeam.includes(userId); - userIsAlreadyInATeam && - toast.error( - 'Your user has been found in this team. Please select another team to add your user.', - ); - } const some = condition.obj ? !props.userTeamsById.some(x => x._id === result._id) : condition.TEAM_NAME @@ -90,8 +74,9 @@ const AddTeamPopup = React.memo(props => { toast.success('Team assigned successfully'); //toast notification } else { // when the user typed something but didn't select a team - onValidation(false); - setIsNotDisplayAlert(false); + toast.error( + 'Your user has been found in this team. Please select another team to add your user.', + ); } }; diff --git a/src/components/WeeklySummary/__test__/WeeklySummary.test.js b/src/components/WeeklySummary/__test__/WeeklySummary.test.js index a80bbb4748..eec1c9d24b 100644 --- a/src/components/WeeklySummary/__test__/WeeklySummary.test.js +++ b/src/components/WeeklySummary/__test__/WeeklySummary.test.js @@ -74,7 +74,7 @@ describe('WeeklySummary Redux related actions', () => { server.use( rest.put(url, (req, res, ctx) => { const { userId } = req.params; - return res(ctx.json({ _id: userId }), ctx.status(200)); + return res(ctx.json({ _id: '1' }), ctx.status(200)); }), ); const response = await store.dispatch(updateWeeklySummaries('1', weeklySummariesMockData)); From 7d7772717aa078f9c3021382aafb106d3a7fe7d5 Mon Sep 17 00:00:00 2001 From: Peterson Rodrigues dos Santos Date: Mon, 17 Jun 2024 18:07:12 -0300 Subject: [PATCH 07/11] Peterson_Implement_toast_when_user_is_already_in_a_team --- src/actions/allTeamsAction.js | 56 ++++++++-------- .../TeamsAndProjects/AddTeamPopup.jsx | 66 +++++++++++-------- .../TeamsAndProjects/AddTeamsAutoComplete.jsx | 59 +++++++++-------- 3 files changed, 99 insertions(+), 82 deletions(-) diff --git a/src/actions/allTeamsAction.js b/src/actions/allTeamsAction.js index c48a71a5aa..5b560cec13 100644 --- a/src/actions/allTeamsAction.js +++ b/src/actions/allTeamsAction.js @@ -18,7 +18,7 @@ import { * set allteams in store * @param payload : allteams [] */ -export const teamMembersFectchACtion = (payload) => ({ +export const teamMembersFectchACtion = payload => ({ type: RECEIVE_ALL_USER_TEAMS, payload, }); @@ -27,7 +27,7 @@ export const teamMembersFectchACtion = (payload) => ({ * Action for Updating an teams * @param {*} team : the updated user */ -export const userTeamsUpdateAction = (team) => ({ +export const userTeamsUpdateAction = team => ({ type: USER_TEAMS_UPDATE, team, }); @@ -45,7 +45,7 @@ export const addNewTeam = (payload, status) => ({ * Delete team action * @param {*} team : the deleted team */ -export const teamsDeleteAction = (team) => ({ +export const teamsDeleteAction = team => ({ type: TEAMS_DELETE, team, }); @@ -72,7 +72,7 @@ export const teamUsersFetchAction = () => ({ * setting team users in store * @param payload : allteams [] */ -export const teamUsersFetchCompleteAction = (payload) => ({ +export const teamUsersFetchCompleteAction = payload => ({ type: RECEIVE_TEAM_USERS, payload, }); @@ -81,7 +81,7 @@ export const teamUsersFetchCompleteAction = (payload) => ({ * Error when setting the team users list * @param payload : error status code */ -export const teamUsersFetchErrorAction = (payload) => ({ +export const teamUsersFetchErrorAction = payload => ({ type: FETCH_TEAM_USERS_ERROR, payload, }); @@ -89,7 +89,7 @@ export const teamUsersFetchErrorAction = (payload) => ({ /* delete team member action */ -export const teamMemberDeleteAction = (member) => ({ +export const teamMemberDeleteAction = member => ({ type: TEAM_MEMBER_DELETE, member, }); @@ -97,7 +97,7 @@ export const teamMemberDeleteAction = (member) => ({ /* delete team member action */ -export const teamMemberAddAction = (member) => ({ +export const teamMemberAddAction = member => ({ type: TEAM_MEMBER_ADD, member, }); @@ -107,9 +107,9 @@ export const teamMemberAddAction = (member) => ({ */ export const getAllUserTeams = () => { const userTeamsPromise = axios.get(ENDPOINTS.TEAM); - return async (dispatch) => { + return async dispatch => { return userTeamsPromise - .then((res) => { + .then(res => { dispatch(teamMembersFectchACtion(res.data)); return res.data; // console.log("getAllUserTeams: res:", res.data) @@ -122,17 +122,20 @@ export const getAllUserTeams = () => { /** * posting new team -*/ -export const postNewTeam = (name, status) => { + */ +export const postNewTeam = (name, status, source) => { const data = { teamName: name, isActive: status }; - const teamCreationPromise = axios.post(ENDPOINTS.TEAM, data); - return (dispatch) => { + + const config = source ? { cancelToken: source.token } : {}; + + const teamCreationPromise = axios.post(ENDPOINTS.TEAM, data, config); + return dispatch => { return teamCreationPromise - .then((res) => { + .then(res => { dispatch(addNewTeam(res.data, true)); return res; // return the server response }) - .catch((error) => { + .catch(error => { if (error.response) { return error.response; // return the server response } else if (error.request) { @@ -141,17 +144,16 @@ export const postNewTeam = (name, status) => { return { status: 500, message: error.message }; } }); - }; + }; }; - /** * delete an existing team * @param {*} teamId - the team to be deleted */ -export const deleteTeam = (teamId) => { - const url = ENDPOINTS.TEAM_DATA(teamId) - return async (dispatch) => { +export const deleteTeam = teamId => { + const url = ENDPOINTS.TEAM_DATA(teamId); + return async dispatch => { try { const deleteTeamResponse = await axios.delete(url); dispatch(teamsDeleteAction(teamId)); @@ -168,7 +170,7 @@ export const deleteTeam = (teamId) => { export const updateTeam = (teamName, teamId, isActive, teamCode) => { const requestData = { teamName, isActive, teamCode }; const url = ENDPOINTS.TEAM_DATA(teamId); - return async (dispatch) => { + return async dispatch => { try { const updateTeamResponse = await axios.put(url, requestData); dispatch(updateTeamAction(teamId, isActive, teamName, teamCode)); @@ -182,12 +184,12 @@ export const updateTeam = (teamName, teamId, isActive, teamCode) => { /** * fetching team members */ -export const getTeamMembers = (teamId) => { +export const getTeamMembers = teamId => { const teamMembersPromise = axios.get(ENDPOINTS.TEAM_USERS(teamId)); - return async (dispatch) => { + return async dispatch => { await dispatch(teamUsersFetchAction()); return teamMembersPromise - .then((res) => { + .then(res => { dispatch(teamUsersFetchCompleteAction(res.data)); return res.data; }) @@ -204,7 +206,7 @@ export const getTeamMembers = (teamId) => { export const deleteTeamMember = (teamId, userId) => { const requestData = { userId, operation: 'UnAssign' }; const teamMemberDeletePromise = axios.post(ENDPOINTS.TEAM_USERS(teamId), requestData); - return async (dispatch) => { + return async dispatch => { teamMemberDeletePromise.then(() => { dispatch(teamMemberDeleteAction(userId)); }); @@ -217,8 +219,8 @@ export const deleteTeamMember = (teamId, userId) => { export const addTeamMember = (teamId, userId, firstName, lastName, role, addDateTime) => { const requestData = { userId, operation: 'Assign' }; const teamMemberAddPromise = axios.post(ENDPOINTS.TEAM_USERS(teamId), requestData); - return async (dispatch) => { - teamMemberAddPromise.then((res) => { + return async dispatch => { + teamMemberAddPromise.then(res => { dispatch(teamMemberAddAction(res.data.newMember)); }); }; diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx index 61a1c36445..7e09ef8a13 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx @@ -6,14 +6,11 @@ import { toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import '../../Header/DarkMode.css'; import { postNewTeam, getAllUserTeams } from '../../../../src/actions/allTeamsAction'; - +import axios from 'axios'; const AddTeamPopup = React.memo(props => { const { darkMode } = props; const dispatch = useDispatch(); - const closePopup = () => { - props.onClose(); - }; const [selectedTeam, onSelectTeam] = useState(undefined); const [isValidTeam, onValidation] = useState(true); @@ -26,7 +23,11 @@ const AddTeamPopup = React.memo(props => { const [isDuplicateTeam, setDuplicateTeam] = useState(false); const [isNotDisplayAlert, setIsNotDisplayAlert] = useState(false); const [autoComplete, setAutoComplete] = useState(null); - const [isloading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const closePopup = () => { + props.onClose(); + }; const format = result => result @@ -86,32 +87,39 @@ const AddTeamPopup = React.memo(props => { setAutoComplete(0); }; + const axiosResponseExceededTimeout = source => { + setIsLoading(false); + source.cancel(); + }; + const onCreateTeam = async () => { if (newTeamName !== '') { + const CancelToken = axios.CancelToken; + const source = CancelToken.source(); + const timeout = setTimeout(() => axiosResponseExceededTimeout(source), 20000); + setIsLoading(true); - const response = await dispatch(postNewTeam(newTeamName, newTeamIsActive)); - try { - if (response.status === 200) { - setNewTeamName(''); - setNewTeamIsActive(true); - setDuplicateTeam(false); - - // Get updated teams list and select the new team - await dispatch(getAllUserTeams()); - toast.success('Team created successfully'); - const newTeam = response.data; // Assuming response contains the new team data - onSelectTeam(newTeam); - setSearchText(newTeam.teamName); // Update search text to reflect new team name - } - } catch (error) { - if (response.status === 400) { - setDuplicateTeam(true); - setIsLoading(false); - } else { - toast.error('Error occurred while creating team'); - } - } finally { + const response = await dispatch(postNewTeam(newTeamName, newTeamIsActive, source)); + clearTimeout(timeout); + if (response.status === 200) { + setNewTeamName(''); + setNewTeamIsActive(true); + setDuplicateTeam(false); + + // Get updated teams list and select the new team + await dispatch(getAllUserTeams()); + toast.success('Team created successfully'); + const newTeam = response.data; // Assuming response contains the new team data + onSelectTeam(newTeam); + setSearchText(newTeam.teamName); // Update search text to reflect new team name + setIsLoading(false); + } else { setIsLoading(false); + const messageToastError = + response.status === 500 + ? 'No response received from the server' + : 'Error occurred while creating team'; + response.status === 403 ? setDuplicateTeam(true) : toast.error(messageToastError); } } else { onNewTeamValidation(false); @@ -166,9 +174,9 @@ const AddTeamPopup = React.memo(props => { onValidation(false); } }} - disabled={isloading} + disabled={isLoading} > - {isloading ? : 'Confirm'} + {isLoading ? : 'Confirm'} {!isValidTeam && searchText && isNotDisplayAlert && !selectedTeam && ( diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx index 9238361e68..79a6226a50 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx @@ -1,6 +1,7 @@ import React from 'react'; import { Dropdown, Input } from 'reactstrap'; import './TeamsAndProjects.css'; +import { toast } from 'react-toastify'; const AddTeamsAutoComplete = React.memo(props => { const [isOpen, toggle] = React.useState(false); @@ -30,7 +31,7 @@ const AddTeamsAutoComplete = React.memo(props => { }} /> - {props.searchText !== '' && props.teamsData && props.teamsData.allTeams.length > 0 ? ( + {props.searchText !== '' && props.teamsData ? (
{ style={{ marginTop: '0px', width: '100%' }} > {props.teamsData.allTeams - .filter(team => { - if (team.teamName.toLowerCase().indexOf(props.searchText.toLowerCase()) > -1) { - return team; - } - }) - .slice(0, 10) - .map(item => ( + ? props.teamsData.allTeams + .filter(team => { + if (team.teamName.toLowerCase().indexOf(props.searchText.toLowerCase()) > -1) + return team; + else return; + }) + .slice(0, 10) + .map(item => ( +
{ + props.setSearchText(item.teamName); + toggle(false); + props.onDropDownSelect(item); + }} + > + {item.teamName} +
+ )) + : toast.error('No teams found')} + + {props.teamsData.allTeams ? ( + props.teamsData.allTeams.every( + team => team.teamName.toLowerCase() !== props.searchText.toLowerCase(), + ) && (
{ - props.setSearchText(item.teamName); toggle(false); - props.onDropDownSelect(item); + props.onCreateNewTeam(props.searchText); }} > - {item.teamName} + Create new team: {props.searchText}
- ))} - - {props.teamsData.allTeams.every( - team => team.teamName.toLowerCase() !== props.searchText.toLowerCase(), - ) && ( -
{ - toggle(false); - props.onCreateNewTeam(props.searchText); - }} - > - Create new team: {props.searchText} -
+ ) + ) : ( + <> )}
) : ( From c149b2b472c02b872ed0fa7d728c933aec127b61 Mon Sep 17 00:00:00 2001 From: Peterson Rodrigues dos Santos Date: Fri, 21 Jun 2024 11:43:17 -0300 Subject: [PATCH 08/11] Peterson_Implement_toast_when_user_is_already_in_a_team --- .../TeamsAndProjects/AddTeamPopup.jsx | 23 +++++++++---------- .../TeamsAndProjects/AddTeamsAutoComplete.jsx | 4 ++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx index 7e09ef8a13..18a276899c 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx @@ -21,12 +21,13 @@ const AddTeamPopup = React.memo(props => { const [newTeamName, setNewTeamName] = useState(''); const [newTeamIsActive, setNewTeamIsActive] = useState(true); const [isDuplicateTeam, setDuplicateTeam] = useState(false); - const [isNotDisplayAlert, setIsNotDisplayAlert] = useState(false); + const [isNotDisplayAlert, setIsNotDisplayAlert] = useState(true); const [autoComplete, setAutoComplete] = useState(null); const [isLoading, setIsLoading] = useState(false); const closePopup = () => { props.onClose(); + !isNotDisplayAlert && setIsNotDisplayAlert(true); }; const format = result => @@ -36,18 +37,17 @@ const AddTeamPopup = React.memo(props => { .replace(/\s+/g, ''); const IfTheUserNotSelectedSuggestionAutoComplete = () => { + // prettier-ignore + if(searchText === '') {onValidation(false); return;} + const filterTeamData = props.teamsData.allTeams.filter( item => format(item.teamName) === format(searchText), - ); + )[0]; - if (filterTeamData.length > 0) { - const arrayToObj = filterTeamData.reduce((obj, item) => (obj = item), {}); - onAssignTeam(arrayToObj); - } else { - setIsNotDisplayAlert(true); - onValidation(false); - return; - } + if (filterTeamData) { + onAssignTeam(filterTeamData); + !isNotDisplayAlert && setIsNotDisplayAlert(true); + } else setIsNotDisplayAlert(false); }; const onAssignTeam = result => { @@ -160,7 +160,6 @@ const AddTeamPopup = React.memo(props => { newTeamName={newTeamName} setSearchText={setSearchText} // Added setSearchText prop setAutoComplete={setAutoComplete} - setIsNotDisplayAlert={setIsNotDisplayAlert} /> - {!isValidTeam && searchText && isNotDisplayAlert && !selectedTeam && ( + {!isNotDisplayAlert && ( Oops, this team does not exist! Create it if you want it. )} diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx index 79a6226a50..c0321be11e 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamsAutoComplete.jsx @@ -7,9 +7,9 @@ const AddTeamsAutoComplete = React.memo(props => { const [isOpen, toggle] = React.useState(false); React.useEffect(() => { - if (!props.selectedTeam && props.setIsNotDisplayAlert) props.setSearchText(''); + if (!props.selectedTeam) props.setSearchText(''); else props.setSearchText(props.selectedTeam.teamName); - }, [props.selectedTeam, props.setSearchText, props.setIsNotDisplayAlert]); + }, [props.selectedTeam, props.setSearchText]); return ( Date: Wed, 26 Jun 2024 09:05:59 -0300 Subject: [PATCH 09/11] Peterson_Implement_toast_when_user_is_already_in_a_team --- src/components/WeeklySummary/__test__/WeeklySummary.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/WeeklySummary/__test__/WeeklySummary.test.js b/src/components/WeeklySummary/__test__/WeeklySummary.test.js index eec1c9d24b..d3a9a1abe0 100644 --- a/src/components/WeeklySummary/__test__/WeeklySummary.test.js +++ b/src/components/WeeklySummary/__test__/WeeklySummary.test.js @@ -74,7 +74,7 @@ describe('WeeklySummary Redux related actions', () => { server.use( rest.put(url, (req, res, ctx) => { const { userId } = req.params; - return res(ctx.json({ _id: '1' }), ctx.status(200)); + return res(ctx.json({ _id: userId }), ctx.status(200)); }), ); const response = await store.dispatch(updateWeeklySummaries('1', weeklySummariesMockData)); @@ -87,4 +87,4 @@ describe('WeeklySummary Redux related actions', () => { expect(response).toBe(404); }); }); -}); +}); \ No newline at end of file From 26000c602bfc01c3226d3274f4418a9410f08087 Mon Sep 17 00:00:00 2001 From: Peterson Rodrigues Date: Wed, 26 Jun 2024 09:53:14 -0300 Subject: [PATCH 10/11] Update WeeklySummary.test.js --- src/components/WeeklySummary/__test__/WeeklySummary.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/WeeklySummary/__test__/WeeklySummary.test.js b/src/components/WeeklySummary/__test__/WeeklySummary.test.js index d3a9a1abe0..a80bbb4748 100644 --- a/src/components/WeeklySummary/__test__/WeeklySummary.test.js +++ b/src/components/WeeklySummary/__test__/WeeklySummary.test.js @@ -87,4 +87,4 @@ describe('WeeklySummary Redux related actions', () => { expect(response).toBe(404); }); }); -}); \ No newline at end of file +}); From 59f55bb9e441e2f96efca0848b4f90e210694745 Mon Sep 17 00:00:00 2001 From: Peterson Rodrigues dos Santos Date: Wed, 26 Jun 2024 15:41:53 -0300 Subject: [PATCH 11/11] Peterson_Implement_toast_when_user_is_already_in_a_team --- .../TeamsAndProjects/AddTeamPopup.jsx | 93 +++++++------------ .../TeamsAndProjects/AddTeamsAutoComplete.jsx | 8 -- .../__tests__/AddTeamPopup.test.js | 4 +- 3 files changed, 34 insertions(+), 71 deletions(-) diff --git a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx index 18a276899c..c81471e3cd 100644 --- a/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx +++ b/src/components/UserProfile/TeamsAndProjects/AddTeamPopup.jsx @@ -18,11 +18,8 @@ const AddTeamPopup = React.memo(props => { const [searchText, setSearchText] = useState(''); // add searchText state // states and onrs for the new team form - const [newTeamName, setNewTeamName] = useState(''); - const [newTeamIsActive, setNewTeamIsActive] = useState(true); const [isDuplicateTeam, setDuplicateTeam] = useState(false); const [isNotDisplayAlert, setIsNotDisplayAlert] = useState(true); - const [autoComplete, setAutoComplete] = useState(null); const [isLoading, setIsLoading] = useState(false); const closePopup = () => { @@ -30,61 +27,51 @@ const AddTeamPopup = React.memo(props => { !isNotDisplayAlert && setIsNotDisplayAlert(true); }; - const format = result => - result - .toLowerCase() - .trim() - .replace(/\s+/g, ''); + // prettier-ignore + const format = result => result.toLowerCase().trim().replace(/\s+/g, ''); + + const FilteredToTeamSpecific = arrayOrObj => { + const result = props.teamsData.allTeams.filter( + item => format(item.teamName) === format(searchText), + ); + if (result.length > 0) { + if (arrayOrObj) return result[0]; + else return result; + } else return undefined; + }; const IfTheUserNotSelectedSuggestionAutoComplete = () => { // prettier-ignore if(searchText === '') {onValidation(false); return;} - const filterTeamData = props.teamsData.allTeams.filter( - item => format(item.teamName) === format(searchText), - )[0]; + const filterTeamData = FilteredToTeamSpecific(true); if (filterTeamData) { onAssignTeam(filterTeamData); + onValidation(true); !isNotDisplayAlert && setIsNotDisplayAlert(true); } else setIsNotDisplayAlert(false); }; const onAssignTeam = result => { - const condition = { - TEAM_NAME: autoComplete === 0, - obj: autoComplete === 1, - selectedTeam: selectedTeam, - result: result, - }; - - if (!searchText) { - onValidation(false); - return; - } - const some = condition.obj - ? !props.userTeamsById.some(x => x._id === result._id) - : condition.TEAM_NAME - ? !props.userTeamsById.some(x => x._id === selectedTeam._id) - : null; - - if (condition && some) { - props.onSelectAssignTeam(condition.TEAM_NAME ? selectedTeam : condition.obj ? result : null); + // prettier-ignore + if (!searchText) {onValidation(false); return;} /* when the user typed nothing */ + + const idToCheck = result ? result._id : selectedTeam._id; + + const some = !props.userTeamsById.some(x => x._id === idToCheck); + + if ((result || selectedTeam) && some) { + props.onSelectAssignTeam(result ? result : selectedTeam); + + toast.success('Team assigned successfully '); // toast notification setSearchText(''); - onValidation(true); - toast.success('Team assigned successfully'); //toast notification - } else { - // when the user typed something but didn't select a team + + selectedTeam && (onSelectTeam(undefined), onValidation(false)); + } else toast.error( 'Your user has been found in this team. Please select another team to add your user.', ); - } - }; - - const selectTeam = team => { - onSelectTeam(team); - setSearchText(team.teamName); - setAutoComplete(0); }; const axiosResponseExceededTimeout = source => { @@ -93,17 +80,15 @@ const AddTeamPopup = React.memo(props => { }; const onCreateTeam = async () => { - if (newTeamName !== '') { + if (searchText !== '') { const CancelToken = axios.CancelToken; const source = CancelToken.source(); const timeout = setTimeout(() => axiosResponseExceededTimeout(source), 20000); setIsLoading(true); - const response = await dispatch(postNewTeam(newTeamName, newTeamIsActive, source)); + const response = await dispatch(postNewTeam(searchText, true, source)); clearTimeout(timeout); if (response.status === 200) { - setNewTeamName(''); - setNewTeamIsActive(true); setDuplicateTeam(false); // Get updated teams list and select the new team @@ -131,10 +116,6 @@ const AddTeamPopup = React.memo(props => { onNewTeamValidation(true); }, [props.open]); - useEffect(() => { - dispatch(getAllUserTeams()); - }, [newTeamName, newTeamIsActive, dispatch]); - return ( {