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

Bug fix logout deleted user #514

Merged
merged 2 commits into from
Sep 27, 2024
Merged
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
215 changes: 214 additions & 1 deletion package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
"file-loader": "^6.2.0",
"graphql": "^16.7.1",
"html-webpack-plugin": "^5.5.0",
"husky": "^8.0.1",
"husky": "^8.0.3",
"install": "^0.13.0",
"jest": "^28.1.3",
"jest-axe": "^8.0.0",
Expand Down Expand Up @@ -178,5 +178,6 @@
"lint-staged": {
"*.{js,ts,tsx}": "eslint --fix",
"*.{js,ts,html,css,md}": "prettier --write \"./**/*.{js,ts,jsx,tsx,json}\""
}
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
3 changes: 2 additions & 1 deletion public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,5 +345,6 @@
"Documentation updated successfully": "Documentation updated successfully",
"Please fill all fields": "Please fill all fields",
"Boost your organization": "Boost your organizations productivity with Pulse",
"Please wait to be added to a program or cohort": "Please wait to be added to a program or cohort"
"Please wait to be added to a program or cohort": "Please wait to be added to a program or cohort",
"Are you sure you want to delete this user?": "Are you sure you want to delete this user?"
}
5 changes: 3 additions & 2 deletions public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@
"Provide Quantity range between 1-2": "Fournir une gamme de quantité comprise entre 1-2",
"Provide Professional_Skills range between 1-2": "Fournir une gamme de compétences professionnelles comprise entre 1-2",
"Sprint Ratings": "Sprint Notations",
"Please wait to be added to a program or cohort": "Veuillez attendre d'être ajouté à un programme ou à une cohorte",
"Enter all the required information": "Entrez toutes les informations requises"
"Please wait to be added to a program or cohort": "Veuillez attendre d'être ajouté à un programme ou à une cohorte",
"Enter all the required information": "Entrez toutes les informations requises",
"Are you sure you want to delete this user?": "Êtes-vous sûr de vouloir supprimer cet utilisateur ?"
}
3 changes: 2 additions & 1 deletion public/locales/kn/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -452,5 +452,6 @@
"Provide Professional_Skills range between 1-2": "Tanga ubuhanga buri hagati ya 1-2",
"Sprint Ratings": "Amanota ya Sprint",
"Please wait to be added to a program or cohort": "Tegereza tukongere muri porogarame cyangwa itsinda",
"Enter all the required information": "Shyiramo amakuru yose asabwa"
"Enter all the required information": "Shyiramo amakuru yose asabwa",
"Are you sure you want to delete this user?": "urashaka kwemeza ikigikorwa cyo gusiba uyumuntu ?"
}
2 changes: 1 addition & 1 deletion src/components/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ function DataTable({ data, columns, title, loading, className }: TableData) {
colSpan={columns.length}
className="px-6 py-4 text-sm text-center text-gray-500 dark:text-gray-300 "
>
Loading...
A Loading...
</td>
</tr>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ManagerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ function ManagerCard() {
grade,
teamname: team.name,
coordinator: team?.cohort?.coordinator?.profile
? team.cohort?.coordinator.profile.name
? team.cohort?.coordinator?.profile?.name
: team?.cohort?.coordinator?.email,
ttl: team?.ttl?.profile ? team.ttl.profile.name : team?.ttl?.email,
phase: team?.cohort?.phase?.name,
Expand Down
54 changes: 28 additions & 26 deletions src/components/teamDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ function TeamDetails() {
cohort: team?.cohort?.name,
teamname: team.name,
coordinator: team?.cohort?.coordinator?.profile
? team.cohort?.coordinator.profile.name
? team?.cohort?.coordinator?.profile?.name
: team?.cohort?.coordinator?.email,
ttl: team?.ttl?.profile ? team.ttl.profile.name : team?.ttl?.email,
ttl: team?.ttl?.profile ? team?.ttl?.profile?.name : team?.ttl?.email,
Qty,
Qnty,
skills,
Expand Down Expand Up @@ -228,12 +228,12 @@ function TeamDetails() {
<h1 className="font-bold text-xl">{teamname}</h1>
<div className="border-r-2 h-6 border-black" />
<h1 className="font-extrabold text-xl">
{selectedTeam.cohort}
{selectedTeam?.cohort}
</h1>
</div>
<div className="relative dark:text-black">
<p>Coordinator: {selectedTeam?.coordinator}</p>
<p>TTL: {selectedTeam.ttl}</p>
<p>TTL: {selectedTeam?.ttl}</p>
</div>
</div>

Expand Down Expand Up @@ -285,12 +285,12 @@ function TeamDetails() {
<div className="flex flex-row lg:flex-row ">
<div className="w-[90px]">
<CircularProgressbar
value={(selectedTeam.Qty / 2) * 100}
text={`${selectedTeam.Qty.toFixed(1)}`}
className={getRatingColorClass(selectedTeam.Qty)}
value={(selectedTeam?.Qty / 2) * 100}
text={`${selectedTeam?.Qty.toFixed(1)}`}
className={getRatingColorClass(selectedTeam?.Qty)}
styles={{
path: {
stroke: getColor(selectedTeam.Qty),
stroke: getColor(selectedTeam?.Qty),
transition: 'stroke-dashoffset 0.5s ease 0s',
},
trail: {
Expand All @@ -310,10 +310,11 @@ function TeamDetails() {
<ul className="list-disc">
<li>Quality</li>
</ul>
<span style={{ color: getColor(selectedTeam.Qty) }}>
{selectedTeam.Qty >= 1.5 && selectedTeam.Qty <= 2
<span style={{ color: getColor(selectedTeam?.Qty) }}>
{selectedTeam?.Qty >= 1.5 && selectedTeam?.Qty <= 2
? 'Good'
: selectedTeam.Qty >= 1 && selectedTeam.Qty < 1.5
: selectedTeam?.Qty >= 1 &&
selectedTeam?.Qty < 1.5
? 'Improve'
: 'Poor'}
</span>
Expand All @@ -322,11 +323,11 @@ function TeamDetails() {
<div className=" flex flex-row lg:flex-row ">
<div className="w-[90px] ">
<CircularProgressbar
value={(selectedTeam.Qnty / 2) * 100}
text={`${selectedTeam.Qnty.toFixed(1)}`}
value={(selectedTeam?.Qnty / 2) * 100}
text={`${selectedTeam?.Qnty.toFixed(1)}`}
styles={{
path: {
stroke: getColor(selectedTeam.Qnty),
stroke: getColor(selectedTeam?.Qnty),
transition: 'stroke-dashoffset 0.5s ease 0s',
},
trail: {
Expand All @@ -346,11 +347,12 @@ function TeamDetails() {
<ul className="list-disc ">
<li>Quantity</li>
</ul>
<span style={{ color: getColor(selectedTeam.Qnty) }}>
{selectedTeam.Qnty >= 1.5 && selectedTeam.Qnty <= 2
<span style={{ color: getColor(selectedTeam?.Qnty) }}>
{selectedTeam?.Qnty >= 1.5 &&
selectedTeam?.Qnty <= 2
? 'Good'
: selectedTeam.Qnty >= 1 &&
selectedTeam.Qnty < 1.5
: selectedTeam?.Qnty >= 1 &&
selectedTeam?.Qnty < 1.5
? 'Improve'
: 'Poor'}
</span>
Expand All @@ -360,11 +362,11 @@ function TeamDetails() {
<div className=" w-full flex flex-row">
<div className="w-[90px] ">
<CircularProgressbar
value={(selectedTeam.skills / 2) * 100}
text={`${selectedTeam.skills.toFixed(1)}`}
value={(selectedTeam?.skills / 2) * 100}
text={`${selectedTeam?.skills.toFixed(1)}`}
styles={{
path: {
stroke: getColor(selectedTeam.skills),
stroke: getColor(selectedTeam?.skills),
transition: 'stroke-dashoffset 0.5s ease 0s',
},
trail: {
Expand All @@ -384,12 +386,12 @@ function TeamDetails() {
<ul className="list-disc ">
<li>Professionalism</li>
</ul>
<span style={{ color: getColor(selectedTeam.skills) }}>
{selectedTeam.skills >= 1.5 &&
selectedTeam.skills <= 2
<span style={{ color: getColor(selectedTeam?.skills) }}>
{selectedTeam?.skills >= 1.5 &&
selectedTeam?.skills <= 2
? 'Good'
: selectedTeam.skills >= 1 &&
selectedTeam.skills < 1.5
: selectedTeam?.skills >= 1 &&
selectedTeam?.skills < 1.5
? 'Improve'
: 'Poor'}
</span>
Expand Down
11 changes: 11 additions & 0 deletions src/containers/admin-dashBoard/DeleteUserMutation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { gql } from '@apollo/client';

const DELETE_USER_MUTATION = gql`
mutation DeleteUser($input: DeleteUserInput!) {
deleteUser(input: $input) {
message
}
}
`;

export default DELETE_USER_MUTATION;
120 changes: 109 additions & 11 deletions src/containers/admin-dashBoard/ManagerRoles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import rolemanagement from '../../dummyData/rolemanagement.json';
import useDocumentTitle from '../../hook/useDocumentTitle';
import Button from './../../components/Buttons';
import devs from '../../dummyData/rolemanagement.json';
import DELETE_USER_MUTATION from '../admin-dashBoard/DeleteUserMutation';
import CREATE_ROLE_MUTATION from '../admin-dashBoard/createRoleMutation';
import GET_ROLE_QUERY from '../admin-dashBoard/GetRolesQuery';
import ASSIGN_ROLE_MUTATION from '../admin-dashBoard/AssignRolesMutation';
Expand All @@ -26,7 +27,6 @@ const AdminSission = () => {
useDocumentTitle('Roles & Access');
const [addMemberModel, setAddMemberModel] = useState(false);
const [deleteModel, setDeleteModel] = useState(false);

const [GetAllRoles] = useLazyQuery(GET_ROLE_QUERY);
const [developers, setDevelopers] = useState(devs);
const [tabName, setTabName] = useState('all');
Expand All @@ -42,9 +42,12 @@ const AdminSission = () => {
const [createUserRole] = useMutation(CREATE_ROLE_MUTATION);
const [updateUserRole] = useMutation(ASSIGN_ROLE_MUTATION);
const [findFilter, setFindFilter] = useState('');
const [loggedUser, setLoggedUser] = useState('');
const [allRoles, setallRoles] = useState<any>();
const [selectingTTL, setSelectingTTL] = useState(false);
const [selectedTeamId, setSelectedTeamId] = useState('');
const [deleteConfirmationModel, setDeleteConfirmationModel] = useState(false); // Modal for confirming deletion

const { loading, error, data } = useQuery(GET_TEAMS, {
variables: { orgToken: localStorage.getItem('orgToken') },
});
Expand All @@ -61,6 +64,32 @@ const AdminSission = () => {
let newState = !deleteModel;
setDeleteModel(newState);
};

const [deleteUser] = useMutation(DELETE_USER_MUTATION, {
onCompleted: (data) => {
if (data.deleteUser.message) {
toast.success('User deleted successfully');
setToggle(!toggle); // Refresh or update state
} else {
toast.error('Failed to delete user');
}
},
onError: (error) => {
toast.error(error.message);
},
});

useEffect(() => {
// Fetch the auth details from local storage
const authData = localStorage.getItem('auth');

if (authData) {
const parsedAuthData = JSON.parse(authData);
const userId = parsedAuthData.userId;
setLoggedUser(userId);
}
}, []);

useEffect(() => {
if (tabName === 'all') {
setDataDev(rolemanagement);
Expand Down Expand Up @@ -224,17 +253,30 @@ const AdminSission = () => {
accessor: '',
/* istanbul ignore next */
Cell: ({ row }: any) => (
<p
className="text-red-500 whitespace-no-wrap cursor-pointer"
onClick={
/* istanbul ignore next */ () => {
/* istanbul ignore next */
removeAssignModel(row.original);
<div className="flex gap-4">
<p
className="text-red-500 whitespace-no-wrap cursor-pointer"
onClick={
/* istanbul ignore next */ () => {
/* istanbul ignore next */
removeAssignModel(row.original);
}
}
}
>
{t('Assign')}
</p>
>
{t('Assign')}
</p>
<p
className="text-red-500 whitespace-no-wrap cursor-pointer"
onClick={
/* istanbul ignore next */ () => {
/* istanbul ignore next */
handleDeleteUser(row.original.id);
}
}
>
{t('Delete')}
</p>
</div>
),
},
];
Expand All @@ -252,12 +294,68 @@ const AdminSission = () => {
name: 'ttl',
},
];

const handleDeleteUser = (userId: any) => {
if (loggedUser === userId) {
toast.warn('You can not delete your self!');
} else {
setSelectedUser({ id: userId, role: 'user' });
setDeleteConfirmationModel(true);
}
};

const confirmDeleteUser = () => {
deleteUser({
variables: {
input: { id: selectedUser.id },
context: { userId: selectedUser.id },
},
});
setDeleteConfirmationModel(false);
};
console.log(selectedUser);

/* istanbul ignore next */
return (
<>
{users && allRoless ? (
<>
{/* ... Existing code ... */}
{/* =========================== Start:: Delete Confirmation Modal =============================== */}
<div
className={`w-screen h-screen bg-black bg-opacity-30 backdrop-blur-sm fixed top-0 left-0 z-20 flex items-center justify-center px-4 ${
deleteConfirmationModel === true ? 'block' : 'hidden'
}`}
>
<div className="bg-white dark:bg-dark-bg w-full sm:w-3/4 md:w-1/2 xl:w-4/12 rounded-lg p-4 pb-8">
<div className="card-title w-full flex justify-center items-center flex-col">
<h3 className="font-bold text-sm text-gray-700 dark:text-white text-center w-11/12">
{t('Are you sure you want to delete this user?')}
</h3>
<hr className=" bg-primary border-b my-3 w-full" />
</div>
<div className="card-body">
<div className="w-full flex justify-between">
<Button
variant="info"
size="sm"
style="w-[30%] md:w-1/4 text-sm font-sans"
onClick={() => setDeleteConfirmationModel(false)}
>
{t('Cancel')}
</Button>
<Button
variant="primary"
size="sm"
style="w-[30%] md:w-1/4 text-sm font-sans"
onClick={confirmDeleteUser}
>
{t('Confirm')}
</Button>
</div>
</div>
</div>
</div>
{/* =========================== Start:: delete Session Model =============================== */}
<div
className={`w-screen h-screen bg-black bg-opacity-30 backdrop-blur-sm fixed top-0 left-0 z-20 flex items-center justify-center px-4 ${
Expand Down
17 changes: 17 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,26 @@ import UserProvider from './hook/useAuth';
import App from './App';
import ThemeProvider from './hook/ThemeProvider';

const specificMessagesToLogout = [
'User not authenticated',
'User account does not exist or has been deleted',
'User with this token no longer exist!!',
];
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path, extensions }) => {
if (
specificMessagesToLogout.some((errorMessage) =>
message.includes(errorMessage),
)
) {
const encodedMessage = encodeURIComponent(message); // Encode the message
window.location.href = `/users/login?redirect_message=${encodedMessage}`;
localStorage.removeItem('auth');
localStorage.removeItem('auth_token');
toast.error(message);
}

if (extensions?.code === 'JWT_EXPIRED') {
window.location.pathname = '/users/login';
localStorage.removeItem('auth');
Expand Down
Loading
Loading