Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Luis add email notification to warning tracker #2752

Merged
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
95 changes: 92 additions & 3 deletions src/actions/warnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import {
getWarningByUserId,
postWarningsByUserId,
deleteWarningByUserId,
getCurrentWarnings as getCurrentWarningsAction,
postNewWarning as postNewWarningAction,
deleteWarningDescription as deleteWarningDescriptionAction,
updateWarningDescription as updateWarningDescriptionAction,
editWarningDescription as editWarningDescriptionAction,
} from '../constants/warning';

export const getWarningsByUserId = userId => {
Expand Down Expand Up @@ -35,10 +40,10 @@ export const postWarningByUserId = warningData => {
const response = await dispatch(postWarningsByUserId(res.data));
return response.payload.warnings;
} catch (error) {
if (error.response && error.response.status === 400) {
return { error: 'Error occured when posting' };
if (error.response && error.response.status === 200) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Errors should never get a 200, this also requires backend changes.

return { error: error.message };
} else {
return { error: 'Something else went wrong' };
return { error: error };
}
}
};
Expand All @@ -61,3 +66,87 @@ export const deleteWarningsById = (warningId, personId) => {
}
};
};

/* WARNING DESCRIPTION ACTIONS */

export const getWarningDescriptions = () => {
const url = ENDPOINTS.GET_CURRENT_WARNINGS();

return async dispatch => {
try {
const res = await axios.get(url);
const response = await dispatch(getCurrentWarningsAction(res.data));
return response.payload.currentWarningDescriptions;
} catch (error) {
if (error.response && error.response.status === 400) {
return { error: error.response.data.message };
} else {
return { error: error };
}
}
};
};
export const postNewWarning = newWarning => {
const url = ENDPOINTS.POST_NEW_WARNING();

return async dispatch => {
try {
// post needs to send an object with a key of newWarning
const res = await axios.post(url, newWarning);
const response = await dispatch(postNewWarningAction(res.data));
return response.payload;
} catch (error) {
if (error.response.status === 422) {
return { error: error.response.data.error };
}

return { error: 'error occured' };
}
};
};

export const deleteWarningDescription = warningDescriptionId => {
const url = ENDPOINTS.DELETE_WARNING_DESCRIPTION(warningDescriptionId);

return async dispatch => {
try {
const res = await axios.delete(url, { data: { warningDescriptionId } });
const response = await dispatch(deleteWarningDescriptionAction(res.data));

return response.payload;
} catch (error) {
return { error: error.message };
}
};
};

export const editWarningDescription = editedWarning => {
const url = ENDPOINTS.EDIT_WARNING_DESCRIPTION();
return async dispatch => {
try {
const res = await axios.put(url, { editedWarning });
const response = await dispatch(editWarningDescriptionAction(res.data));
return response.payload;
} catch (error) {
if (error.response.status === 422) {
return { error: error.response.data.error };
}
return { error: error.message };
}
};
};

export const updateWarningDescription = warningDescriptionId => {
const url = ENDPOINTS.UPDATE_WARNING_DESCRIPTION(warningDescriptionId);

return async dispatch => {
try {
const res = await axios.put(url, { warningDescriptionId });
const response = await dispatch(updateWarningDescriptionAction(res.data));

return response.payload;
} catch (error) {
return { error: error.message };
}
};
};
86 changes: 60 additions & 26 deletions src/components/TeamMemberTasks/TeamMemberTask.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { showTimeOffRequestModal } from '../../actions/timeOffRequestAction';
import GoogleDocIcon from '../common/GoogleDocIcon';
import FollowupCheckButton from './FollowupCheckButton';
import FollowUpInfoModal from './FollowUpInfoModal';
import * as messages from '../../constants/followUpConstants'
import * as messages from '../../constants/followUpConstants';

const NUM_TASKS_SHOW_TRUNCATE = 6;

Expand All @@ -43,6 +43,7 @@ const TeamMemberTask = React.memo(
showWhoHasTimeOff,
onTimeOff,
goingOnTimeOff,
displayUser,
}) => {
const darkMode = useSelector(state => state.theme.darkMode);
const ref = useRef(null);
Expand Down Expand Up @@ -75,7 +76,8 @@ const TeamMemberTask = React.memo(
// these need to be changed to actual permissions...
const rolesAllowedToResolveTasks = ['Administrator', 'Owner'];
const rolesAllowedToSeeDeadlineCount = ['Manager', 'Mentor', 'Administrator', 'Owner'];
const isAllowedToResolveTasks = rolesAllowedToResolveTasks.includes(userRole) || dispatch(hasPermission('resolveTask'));
const isAllowedToResolveTasks =
rolesAllowedToResolveTasks.includes(userRole) || dispatch(hasPermission('resolveTask'));
const isAllowedToSeeDeadlineCount = rolesAllowedToSeeDeadlineCount.includes(userRole);
// ^^^

Expand Down Expand Up @@ -108,21 +110,25 @@ const TeamMemberTask = React.memo(
const followUpMouseoverText = task => {
const progressPersantage = ((task.hoursLogged / task.estimatedHours) * 100).toFixed(2) || 0;
if (progressPersantage < 50) {
return messages.MOUSE_OVER_TEXT_UNDER_50
return messages.MOUSE_OVER_TEXT_UNDER_50;
} else if (progressPersantage >= 50 && progressPersantage < 75) {
return messages.MOUSE_OVER_TEXT_BETWEEN_50_75
return messages.MOUSE_OVER_TEXT_BETWEEN_50_75;
} else if (progressPersantage >= 75 && progressPersantage < 90) {
return messages.MOUSE_OVER_TEXT_BETWEEN_75_90
return messages.MOUSE_OVER_TEXT_BETWEEN_75_90;
} else if (progressPersantage >= 90) {
return messages.MOUSE_OVER_TEXT_OVER_90
return messages.MOUSE_OVER_TEXT_OVER_90;
}
};

return (
<>
<tr ref={ref} className={`table-row ${darkMode ? "bg-yinmn-blue" : ""}`} key={user.personId}>
<tr
ref={ref}
className={`table-row ${darkMode ? 'bg-yinmn-blue' : ''}`}
key={user.personId}
>
{/* green if member has met committed hours for the week, red if not */}
<td colSpan={1} className={`${darkMode ? "bg-yinmn-blue" : ""}`}>
<td colSpan={1} className={`${darkMode ? 'bg-yinmn-blue' : ''}`}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div className="committed-hours-circle">
<FontAwesomeIcon
Expand All @@ -138,7 +144,11 @@ const TeamMemberTask = React.memo(
<i
className="fa fa-clock-o"
aria-hidden="true"
style={{ fontSize: 24, cursor: 'pointer', color: darkMode ? 'lightgray' : 'black' }}
style={{
fontSize: 24,
cursor: 'pointer',
color: darkMode ? 'lightgray' : 'black',
}}
title="Click to see user's timelog"
/>
</Link>
Expand All @@ -150,7 +160,7 @@ const TeamMemberTask = React.memo(
<tr>
<td className="team-member-tasks-user-name">
<Link
className='team-member-tasks-user-name-link'
className="team-member-tasks-user-name-link"
to={`/userprofile/${user.personId}`}
style={{
color:
Expand All @@ -159,8 +169,10 @@ const TeamMemberTask = React.memo(
) &&
currentDate.isBefore(moment(user.timeOffTill, 'YYYY-MM-DDTHH:mm:ss.SSSZ'))
? 'rgba(128, 128, 128, 0.5)'
: darkMode ? "#007BFF" : undefined,
fontSize: '20px'
: darkMode
? '#007BFF'
: undefined,
fontSize: '20px',
}}
>{`${user.name}`}</Link>
{canGetWeeklySummaries && <GoogleDocIcon link={userGoogleDocLink} />}
Expand All @@ -172,11 +184,14 @@ const TeamMemberTask = React.memo(
user={user}
userRole={userRole}
personId={user.personId}
displayUser={displayUser}
/>
</td>
<td data-label="Time" className={`team-clocks ${darkMode ? "text-light" : ""}`}>
<u className={darkMode ? "text-azure" : ""}>{user.weeklycommittedHours ? user.weeklycommittedHours : 0}</u> /
<font color="green"> {thisWeekHours ? thisWeekHours.toFixed(1) : 0}</font> /
<td data-label="Time" className={`team-clocks ${darkMode ? 'text-light' : ''}`}>
<u className={darkMode ? 'text-azure' : ''}>
{user.weeklycommittedHours ? user.weeklycommittedHours : 0}
</u>{' '}
/<font color="green"> {thisWeekHours ? thisWeekHours.toFixed(1) : 0}</font> /
<font color="red"> {totalHoursRemaining.toFixed(1)}</font>
</td>
</tr>
Expand All @@ -190,13 +205,16 @@ const TeamMemberTask = React.memo(
activeTasks.slice(0, numTasksToShow).map((task, index) => {
return (
<tr key={`${task._id}${index}`} className="task-break">
<td data-label="Task(s)" className={`task-align ${darkMode ? "bg-yinmn-blue text-light" : ""}`}>
<td
data-label="Task(s)"
className={`task-align ${darkMode ? 'bg-yinmn-blue text-light' : ''}`}
>
<div className="team-member-tasks-content">
<Link
className='team-member-tasks-content-link'
className="team-member-tasks-content-link"
to={task.projectId ? `/wbs/tasks/${task._id}` : '/'}
data-testid={`${task.taskName}`}
style={{color: darkMode ? "#007BFF" : undefined}}
style={{ color: darkMode ? '#007BFF' : undefined }}
>
<span>{`${task.num} ${task.taskName}`} </span>
</Link>
Expand Down Expand Up @@ -268,7 +286,12 @@ const TeamMemberTask = React.memo(
</div>
</td>
{task.hoursLogged != null && task.estimatedHours != null && (
<td data-label="Progress" className={`team-task-progress ${darkMode ? "bg-yinmn-blue text-light" : ""}`}>
<td
data-label="Progress"
className={`team-task-progress ${
darkMode ? 'bg-yinmn-blue text-light' : ''
}`}
>
{isAllowedToSeeDeadlineCount && (
<span
className="deadlineCount"
Expand All @@ -280,16 +303,24 @@ const TeamMemberTask = React.memo(
)}
<div className="team-task-progress-container">
<span
data-testid={`times-${task.taskName}`}
className={`${darkMode ? 'text-light ' : ''} ${canSeeFollowUpCheckButton ? "team-task-progress-time" : "team-task-progress-time-volunteers"}`}
data-testid={`times-${task.taskName}`}
className={`${darkMode ? 'text-light ' : ''} ${
canSeeFollowUpCheckButton
? 'team-task-progress-time'
: 'team-task-progress-time-volunteers'
}`}
>
{`${parseFloat(task.hoursLogged.toFixed(2))} of ${parseFloat(
task.estimatedHours.toFixed(2),
)}`}
</span>
{canSeeFollowUpCheckButton && (
<>
<FollowupCheckButton moseoverText={followUpMouseoverText(task)} user={user} task={task}/>
<FollowupCheckButton
moseoverText={followUpMouseoverText(task)}
user={user}
task={task}
/>
<FollowUpInfoModal />
</>
)}
Expand All @@ -307,12 +338,15 @@ const TeamMemberTask = React.memo(
)}
</tr>
);
})
}
})}
{canTruncate && (
<tr key="truncate-button-row" className="task-break">
<td className={`task-align`}>
<button type="button" onClick={handleTruncateTasksButtonClick} className={darkMode ? 'text-light' : ''}>
<button
type="button"
onClick={handleTruncateTasksButtonClick}
className={darkMode ? 'text-light' : ''}
>
{isTruncated ? `Show All (${activeTasks.length}) Tasks` : 'Truncate Tasks'}
</button>
</td>
Expand Down Expand Up @@ -370,4 +404,4 @@ const TeamMemberTask = React.memo(
},
);

export default TeamMemberTask;
export default TeamMemberTask;
Loading