Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 50 additions & 11 deletions src/actions/userManagement.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ export const buildUpdatedUserLifecycleDetails = (user, payload) => {
};

const buildBackendPayload = (userDetails, action) => {
console.log('Building backend payload with:', { userDetails, action });
switch (action){
switch (action) {
case UserStatusOperations.ACTIVATE:
return {
action: action,
Expand All @@ -225,29 +224,69 @@ const buildBackendPayload = (userDetails, action) => {
case UserStatusOperations.PAUSE:
return {
action: action,
reactivationDate: userDetails.reactivationDate
reactivationDate: userDetails.reactivationDate,
};
default:
throw new Error(`Unknown lifecycle action: ${action}`);
}
};

export const updateUserLifecycle = (updatedUser, payload) => {
return async dispatch => {
return async (dispatch, getState) => {
const { auth } = getState();
dispatch(userProfileUpdateAction(updatedUser));

const backendPayload = buildBackendPayload(updatedUser, payload.action);
const requestor = {
requestorId: auth.user.userid,
role: auth.user.role,
permissions: auth.user.permissions,
};
const backendPayload = {
...buildBackendPayload(updatedUser, payload.action),
requestor,
};
Comment thread
saitejakaasoju marked this conversation as resolved.
try {
// console.log('Sending PATCH request to update user lifecycle');
await axios.patch(ENDPOINTS.USER_PROFILE(updatedUser._id), backendPayload);

await axios.patch(ENDPOINTS.USER_PROFILE_FIXED(updatedUser._id), backendPayload);
} catch (error) {
toast.error('Error updating user lifecycle:', error);
dispatch(userProfileUpdateAction(payload.originalUser));
throw error;
}
};
}
};

/**
* Update the pause/resume status of a user via the dedicated pause endpoint.
* Requires the 'interactWithPauseUserButton' permission.
* @param {*} user - the user to be paused or resumed
* @param {string} status - UserStatus.Active or UserStatus.Inactive
* @param {*} reactivationDate - the date on which the user should be reactivated
*/
export const updateUserPauseStatus = (user, status, reactivationDate) => {
return async (dispatch, getState) => {
const userProfile = { ...user };
userProfile.isActive = status === UserStatus.Active;
userProfile.reactivationDate = reactivationDate;
const auth = getState().auth;
const requestor = {
requestorId: auth.user.userid,
role: auth.user.role,
permissions: auth.user.permissions,
email: auth.user.email,
};
const patchData = {
status,
reactivationDate: status === UserStatus.Active ? undefined : reactivationDate,
requestor,
};
Comment thread
saitejakaasoju marked this conversation as resolved.
try {
await axios.patch(ENDPOINTS.USER_PAUSE(user._id), patchData);
dispatch(userProfileUpdateAction(userProfile));
} catch (error) {
toast.error('Error updating user pause status:', error);
throw error;
}
};
};

/**
* Update the rehireable status of a user
Expand Down Expand Up @@ -406,4 +445,4 @@ export const changePagination = value => dispatch => {

export const updateUserInfomation = value => dispatch => {
dispatch({ type: START_USER_INFO_UPDATE, payload: value });
};
};
3 changes: 2 additions & 1 deletion src/components/Header/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ export function Header(props) {
props.hasPermission('deleteUserProfile', !isAuthUser ) ||
props.hasPermission('changeUserStatus', !isAuthUser ) ||
props.hasPermission('getUserProfiles', !isAuthUser ) ||
props.hasPermission('setFinalDay', !isAuthUser);
props.hasPermission('setFinalDay', !isAuthUser) ||
props.hasPermission('interactWithPauseUserButton', !isAuthUser);

// Badges
const canAccessBadgeManagement =
Expand Down
10 changes: 5 additions & 5 deletions src/components/PermissionsManagement/Permissions.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@
"key": "toggleInvisibility",
"description": "Gives the user permission to change the invisibility toggle for themselves and others"
},
{
"label": "Interact with Pause User button",
"key": "interactWithPauseUserButton",
"description": "Allows the user to view and interact with the Pause/Resume button on a user profile. \"User Profile\" -> \"Basic Information\" -> \"Status\" -> \"Pause/Resume\""
},
{
"label": "Assign Blue Squares",
"key": "addInfringements",
Expand Down Expand Up @@ -140,11 +145,6 @@
"key": "changeUserRehireableStatus",
"description": "Gives the user permission to change the user status of rehireable or not."
},
{
"label": "Pause User Activity",
"key": "pauseUserActivity",
"description": "Gives the user permission to use the \"Pause\" button to pause user activity on their profile page."
},
{
"label": "Set Final Day",
"key": "setFinalDay",
Expand Down
22 changes: 9 additions & 13 deletions src/components/UserManagement/PauseAndResumeButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { UserStatus } from '../../utils/enums';
import ActivationDatePopup from './ActivationDatePopup';
import { boxStyle, boxStyleDark } from '../../styles';
import { pauseUserAction, activateUserAction } from '../../actions/userLifecycleActions';
import { updateUserPauseStatus } from '../../actions/userManagement';

/**
* @param {*} props
Expand Down Expand Up @@ -34,21 +34,19 @@
* Call back on Pause confirmation button click to trigger the action to update user status
*/
const pauseUser = async reActivationDate => {
setIsLoading(true); // Start loading indicator
setIsLoading(true);
try {
await pauseUserAction(dispatch, props.userProfile, reActivationDate, props.loadUserProfile);
await dispatch(updateUserPauseStatus(props.userProfile, UserStatus.Inactive, reActivationDate));
setIsActive(false);
setActivationDateOpen(false);

// Optimistically update the UI
toast.success('Your Changes were saved successfully.');
} catch (error) {
toast.error('Failed to update the user status.');
// eslint-disable-next-line no-console
console.error(error);
} finally {
setIsLoading(false); // Stop loading indicator
await props.loadUserProfile(); // Ensure state sync
setIsLoading(false);
await props.loadUserProfile();

Check warning on line 49 in src/components/UserManagement/PauseAndResumeButton.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'loadUserProfile' is missing in props validation

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZ1wPW961MRvjmKtvWIu&open=AZ1wPW961MRvjmKtvWIu&pullRequest=5122
}
};

Expand All @@ -57,20 +55,18 @@
*/
const onPauseResumeClick = async (user, status) => {
if (status === UserStatus.Active) {
setIsLoading(true); // Start loading indicator
setIsLoading(true);
try {
await activateUserAction(dispatch, props.userProfile, props.loadUserProfile);
await dispatch(updateUserPauseStatus(props.userProfile, UserStatus.Active, Date.now()));

Check warning on line 60 in src/components/UserManagement/PauseAndResumeButton.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'userProfile' is missing in props validation

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZ1wPW961MRvjmKtvWIv&open=AZ1wPW961MRvjmKtvWIv&pullRequest=5122
setIsActive(true);

// Optimistically update the UI
toast.success('Your Changes were saved successfully.');
} catch (error) {
toast.error('Failed to update the user status.');
// eslint-disable-next-line no-console
console.error(error);
} finally {
setIsLoading(false); // Stop loading indicator
await props.loadUserProfile(); // Ensure state sync
setIsLoading(false);
await props.loadUserProfile();

Check warning on line 69 in src/components/UserManagement/PauseAndResumeButton.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'loadUserProfile' is missing in props validation

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZ1wPW961MRvjmKtvWIw&open=AZ1wPW961MRvjmKtvWIw&pullRequest=5122
}
} else {
setActivationDateOpen(true);
Expand Down
30 changes: 13 additions & 17 deletions src/components/UserManagement/UserManagement.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
deleteUser,
enableEditUserInfo,
disableEditUserInfo,
updateUserPauseStatus,
} from '../../actions/userManagement';
import UserTableHeader from './UserTableHeader';
import UserTableData from './UserTableData';
Expand All @@ -41,8 +42,6 @@
import { getAllTimeOffRequests } from '../../actions/timeOffRequestAction';
import {
scheduleDeactivationAction,
activateUserAction,
pauseUserAction,
deactivateImmediatelyAction,
} from '../../actions/userLifecycleActions';

Expand Down Expand Up @@ -217,12 +216,8 @@
activeInactivePopupOpen: false,
});
}}
onCancelScheduledDeactivation={() =>
activateUserAction(this.props.dispatch, this.state.selectedUser, this.props.getAllUserProfile)
}
onReactivateUser={() =>
activateUserAction(this.props.dispatch, this.state.selectedUser, this.props.getAllUserProfile)
}
onCancelScheduledDeactivation={this.reactivateUser}
onReactivateUser={this.reactivateUser}
/>
<SetUpFinalDayPopUp
open={this.state.finalDayPopupOpen}
Expand Down Expand Up @@ -407,10 +402,15 @@
if (status === UserStatus.Inactive) {
this.setState({ activationDateOpen: true });
} else {
await activateUserAction(this.props.dispatch, user, this.props.getAllUserProfile);
await this.reactivateUser(user);
}
};

reactivateUser = async (user = this.state.selectedUser) => {
await this.props.dispatch(updateUserPauseStatus(user, UserStatus.Active, Date.now()));
await this.props.getAllUserProfile();

Check warning on line 411 in src/components/UserManagement/UserManagement.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'getAllUserProfile' is missing in props validation

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZ1wPW-i1MRvjmKtvWIx&open=AZ1wPW-i1MRvjmKtvWIx&pullRequest=5122
};

onUserUpdate = (updatedUser) => {
const { userProfiles } = this.props.state.allUserProfiles;

Expand Down Expand Up @@ -466,7 +466,7 @@
return;
}
if (status === FinalDay.RemoveFinalDay) {
await activateUserAction(this.props.dispatch, user, this.props.getAllUserProfile);
await this.reactivateUser(user);
} else {
this.setState({
finalDayDateOpen: true,
Expand Down Expand Up @@ -494,14 +494,10 @@
};

pauseUser = async (reactivationDate) => {
// eslint-disable-next-line no-console
console.log('Pausing user with reactivation date:', reactivationDate);
await pauseUserAction(
this.props.dispatch,
this.state.selectedUser,
reactivationDate,
this.props.getAllUserProfile,
await this.props.dispatch(

Check warning on line 497 in src/components/UserManagement/UserManagement.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'dispatch' is missing in props validation

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZ1wPW-i1MRvjmKtvWIy&open=AZ1wPW-i1MRvjmKtvWIy&pullRequest=5122
updateUserPauseStatus(this.state.selectedUser, UserStatus.Inactive, reactivationDate),
);
await this.props.getAllUserProfile();

Check warning on line 500 in src/components/UserManagement/UserManagement.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'getAllUserProfile' is missing in props validation

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZ1wPW-i1MRvjmKtvWIz&open=AZ1wPW-i1MRvjmKtvWIz&pullRequest=5122

this.setState({
activationDateOpen: false,
Expand Down
9 changes: 5 additions & 4 deletions src/components/UserManagement/UserTableData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
const canDeleteUsers = props.hasPermission('deleteUserProfile');
const resetPasswordStatus = props.hasPermission('updatePassword');
const canChangeUserStatus = props.hasPermission('changeUserStatus');
const canInteractWithPauseUserButton = props.hasPermission('interactWithPauseUserButton');
const canSetFinalDay = props.hasPermission('setFinalDay');
const canSeeReports = props.hasPermission('getReports');

Expand Down Expand Up @@ -416,7 +417,7 @@

if (numericValue < 0) {
toast.error(
'If negative hours worked, wed all be on vacation already. Try again, and be sure weekly hours are set to zero or more.',
"If negative hours worked, we'd all be on vacation already. Try again, and be sure weekly hours are set to zero or more.",
);
return;
}
Expand All @@ -434,7 +435,7 @@

{/* PAUSE/RESUME */}
<td>
{!canChangeUserStatus ? (
{!canInteractWithPauseUserButton ? (

Check warning on line 438 in src/components/UserManagement/UserTableData.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unexpected negated condition.

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZ1wPW7O1MRvjmKtvWIi&open=AZ1wPW7O1MRvjmKtvWIi&pullRequest=5122
<Tooltip
placement="bottom"
isOpen={tooltipPauseOpen}
Expand All @@ -452,7 +453,7 @@
onClick={() => {
if (cantUpdateDevAdminDetails(props.user.email, props.authEmail)) {
// eslint-disable-next-line no-alert
alert('STOP! YOU SHOULDNT BE TRYING TO CHANGE THIS. Please reconsider your choices.');
alert("STOP! YOU SHOULDN'T BE TRYING TO CHANGE THIS. Please reconsider your choices.");
return;
}
onReset(true);
Expand All @@ -462,7 +463,7 @@
...(darkMode ? { boxShadow: '0 0 0 0', fontWeight: 'bold' } : boxStyle),
padding: '5px',
}}
disabled={!canChangeUserStatus}
disabled={!canInteractWithPauseUserButton}
id={`btn-pause-profile-${props.user._id}`}
>
{getButtonText()}
Expand Down
Loading
Loading