diff --git a/src/app/privilege/PrivilegeTableRow.jsx b/src/app/privilege/PrivilegeTableRow.jsx index 96f1d1db285eaef898daecd57aaf7905de03eaab..7537e45773778a694de9fbe0655fdb37d9a04980 100644 --- a/src/app/privilege/PrivilegeTableRow.jsx +++ b/src/app/privilege/PrivilegeTableRow.jsx @@ -7,11 +7,16 @@ import EditIcon from "@/static/image/svg/edit.svg" import CancelIcon from "@/static/image/svg/cancel.svg" import CheckIcon from "@/static/image/svg/check.svg" import { useNotification } from '@/context/NotificationContext' +import ConfirmationModal from '../ui/ConfirmationModal' const PrivilegeTableRow = ({ id, name, setPrivileges }) => { const [isUpdating, setIsUpdating] = useState(false) const [privilegeName, setPrivilegeName] = useState(name) const [loadingStatus, setLoadingStatus] = useState(false) const { toggleNotification } = useNotification() + const [isModalOpen, setModalOpen] = useState(false) + const showDeletePopup = () => { + setModalOpen(true); + } useEffect(() => { setPrivilegeName(name) inputRef.current.value = name @@ -87,6 +92,7 @@ const PrivilegeTableRow = ({ id, name, setPrivileges }) => { type: "error" }) } + setModalOpen(false) } const cancelUpdate = () => { setIsUpdating(false) @@ -126,33 +132,41 @@ const PrivilegeTableRow = ({ id, name, setPrivileges }) => { } }, [isUpdating]) return ( - - - setPrivilegeName(event.target.value)} defaultValue={name} type='text' className='disabled:bg-white w-full border-0 rounded-md px-2 enabled:drop-shadow border-none enabled:bg-gray-100 duration-100 h-10 outline-none' /> - - - {!isUpdating - ?
- - -
- :
- - -
- } - - + <> + + + setPrivilegeName(event.target.value)} defaultValue={name} type='text' className='disabled:bg-white w-full border-0 rounded-md px-2 enabled:drop-shadow border-none enabled:bg-gray-100 duration-100 h-10 outline-none' /> + + + {!isUpdating + ?
+ + +
+ :
+ + +
+ } + + + setModalOpen(false)} + onConfirm={handleDelete} + message={`Voulez-vous vraiment supprimer l'habilitation ?`} + /> + ) } diff --git a/src/app/role/CreateRoleForm.jsx b/src/app/role/CreateRoleForm.jsx index 29e177c4b4c3acca9e4b7a9f24036564ddd9883f..546c0c0a863e3f773d39a9c338bddcba18f559b1 100644 --- a/src/app/role/CreateRoleForm.jsx +++ b/src/app/role/CreateRoleForm.jsx @@ -2,10 +2,9 @@ import Loader from '@/components/Loader/Loader' import React, { useState, useRef, useEffect, useMemo } from 'react' import fetchRequest from '../lib/fetchRequest' import { useNotification } from '@/context/NotificationContext' - -const CreateRoleForm = ({ appendRole }) => { +import CancelIcon from "@/static/image/svg/cancel.svg" +const CreateRoleForm = ({ appendRole, setIsOpen }) => { const [isLoading, setIsLoading] = useState(false) - const [error, setError] = useState(null) const [roleName, setRoleName] = useState("") const [privileges, setPrivileges] = useState(null) const [selectedPrivileges, setSelectedPrivileges] = useState([]) @@ -28,7 +27,6 @@ const CreateRoleForm = ({ appendRole }) => { getPrivileges() }, []) const handleRoleNameChange = (event) => { - setError("") setRoleName(event.target.value) } const inputRef = useRef(null) @@ -50,6 +48,7 @@ const CreateRoleForm = ({ appendRole }) => { message: "Le rôle a été créé avec succès", type: "success" }) + setIsOpen(false) } else { setIsLoading(false) if (errors.type === "ValidationError") { @@ -66,6 +65,7 @@ const CreateRoleForm = ({ appendRole }) => { message: "Erreur de validation de rôle", type: "warning" }) + setIsOpen(false) } } else if (status === 409) { @@ -74,12 +74,21 @@ const CreateRoleForm = ({ appendRole }) => { message: "Roles created with 2 or more same privileges", type: "error" }) + setIsOpen(false) + } else if (errors.detail === "Privilege matching query does not exist.") { + toggleNotification({ + visible: true, + message: "Des privilèges que vous avez utilisés ont été supprimés.", + type: "warning" + }) + setIsOpen(false) } else { toggleNotification({ visible: true, message: "Internal Server Error", type: "error" }) + setIsOpen(false) } console.log(errors) } @@ -98,32 +107,37 @@ const CreateRoleForm = ({ appendRole }) => { } var isAllSelected = useMemo(() => privileges ? privileges.every((element) => selectedPrivileges.find((priv) => priv.id === element.id)) : false, [selectedPrivileges, privileges]) return ( -
-

Ajout de Rôle

-
- - -
-

{error}

- {(privileges) ?
-
- -
{!isAllSelected ? "Sélectionner tout" : "désélectionner"}
- -
-
- {privileges?.map((privilege) => { - const isSelected = selectedPrivileges.find((element) => element.id === privilege.id) !== undefined - return
handlePrivilegeClick(privilege)} key={privilege.id} className={`${!isSelected ? 'text-neutral-400 hover:border-neutral-400 hover:text-neutral-500 border-neutral-300 bg-neutral-100' : 'text-indigo-500 hover:border-indigo-500 hover:text-indigo-500 border-indigo-400 bg-indigo-100'} will-change-contents h-6 text-sm flex items-center justify-center duration-150 delay-75 cursor-pointer text-semibold leading-[0] border-2 py-0.5 rounded-full w-fit px-2`}>{privilege.name}
- })} -
-
:
} -
- +
+
+ setIsOpen(false)} className="h-8 w-8 cursor-pointer absolute top-2 right-2 fill-neutral-600" /> + +

Ajout de Rôle

+
+ + +
+ {(privileges) ?
+
+ +
{!isAllSelected ? "Sélectionner tout" : "désélectionner"}
+
+
+ {privileges.length !== 0 ? privileges?.map((privilege) => { + const isSelected = selectedPrivileges.find((element) => element.id === privilege.id) !== undefined + return
handlePrivilegeClick(privilege)} key={privilege.id} className={`${!isSelected ? 'text-neutral-400 hover:border-neutral-400 hover:text-neutral-500 border-neutral-300 bg-neutral-100' : 'text-indigo-500 hover:border-indigo-500 hover:text-indigo-500 border-indigo-400 bg-indigo-100'} will-change-contents h-6 text-sm flex items-center justify-center duration-150 delay-75 cursor-pointer text-semibold leading-[0] border-2 py-0.5 rounded-full w-fit px-2`}>{privilege.name}
+ }) :
+

Pas encore des habilitations

+
} +
+
:
} +
+ +
+
- +
) } diff --git a/src/app/role/RoleTableRows.jsx b/src/app/role/RoleTableRows.jsx index b6c4ea834dea08ad27505cbad054be5ae92908a0..5c44906d31bcc24da8220a392a1eb4b50e4dd520 100644 --- a/src/app/role/RoleTableRows.jsx +++ b/src/app/role/RoleTableRows.jsx @@ -1,67 +1,16 @@ import React, { useEffect, useRef, useState } from 'react' import fetchRequest from '../lib/fetchRequest' -import Loader from '@/components/Loader/Loader' import DeleteIcon from "@/static/image/svg/delete.svg" import EditIcon from "@/static/image/svg/edit.svg" -import CancelIcon from "@/static/image/svg/cancel.svg" -import CheckIcon from "@/static/image/svg/check.svg" import { useNotification } from '@/context/NotificationContext' -const RoleTableRows = ({ name, setRoles, id, privileges }) => { - const [isUpdating, setIsUpdating] = useState(false) - const [roleName, setRoleName] = useState(name) - const [loadingStatus, setLoadingStatus] = useState(false) +import ConfirmationModal from '../ui/ConfirmationModal' + +const RoleTableRows = ({ name, setRoles, id, privileges, setRoleToUpdate }) => { const { toggleNotification } = useNotification() - useEffect(() => { - setRoleName(name) - inputRef.current.value = name - }, [name]) - const handleUpdatePrivilege = async () => { - setLoadingStatus(true) - const { isSuccess, errors, data, status } = await fetchRequest(`/roles/${id}/`, { - method: "PATCH", - body: JSON.stringify({ name: roleName }) - }) - setLoadingStatus(false) - if (isSuccess) { - setRoles((roles) => roles.map((element) => element.id === id ? data.data : element)) - setIsUpdating(false) - toggleNotification({ - visible: true, - message: "Le rôle a été modifé avec succès", - type: "success" - }) - } else { - if (errors.type === "ValidationError") { - if (errors.detail.name) { - toggleNotification({ - type: "warning", - message: "Le nom de rôle existe déjà", - visible: true, - }) - } - else { - toggleNotification({ - visible: true, - message: "Erreur de validation de rôle", - type: "warning" - }) - } - } else if (status === 404) { - toggleNotification({ - visible: true, - message: "Le rôle n'a pas été trouvé", - type: "warning" - }) - } else { - toggleNotification({ - visible: true, - message: "Internal Server Error", - type: "error" - }) - } - console.log(errors) - } + const [isModalOpen, setModalOpen] = useState(false); + const showDeletePopup = () => { + setModalOpen(true); } const handleDelete = async () => { const { isSuccess, errors, status } = await fetchRequest(`/roles/${id}/`, { method: "DELETE" }) @@ -78,7 +27,14 @@ const RoleTableRows = ({ name, setRoles, id, privileges }) => { message: "Le rôle n'a pas été trouvé", type: "warning" }) - } else { + } else if (errors.detail?.indexOf("Cannot delete some instances of model 'Role'") !== -1) { + toggleNotification({ + visible: true, + message: "Impossible de supprimer ce rôle car il est attribué à des utilisateurs", + type: "warning" + }) + } + else { console.log(errors) toggleNotification({ visible: true, @@ -86,73 +42,42 @@ const RoleTableRows = ({ name, setRoles, id, privileges }) => { type: "error" }) } + setModalOpen(false) console.log(errors) } - const cancelUpdate = () => { - setIsUpdating(false) - setRoleName(name) - inputRef.current.value = name - } - const inputRef = useRef(null) - const rowRef = useRef(null) - const handleUpdateBlur = (event) => { - const eventTarget = event.target - let isInsideRowRef = false; - let element = eventTarget; - while (element !== null) { - if (element === rowRef.current) { - isInsideRowRef = true; - break; - } - if (element.parentElement === null) { - isInsideRowRef = false; - break; - } - element = element.parentElement; - } - if (!isInsideRowRef && element?.classList.contains("privilegeRowSVG")) return; - if (!isInsideRowRef) { - cancelUpdate(); - document.removeEventListener("click", handleUpdateBlur); - } - } - useEffect(() => { - if (isUpdating && inputRef?.current) { - inputRef.current.focus() - document.addEventListener("click", handleUpdateBlur) - } - return () => { - document.removeEventListener("click", handleUpdateBlur) - } - }, [isUpdating]) + return ( - - - setRoleName(event.target.value)} defaultValue={name} type='text' className='disabled:bg-white w-full border-0 rounded-md px-2 enabled:drop-shadow border-none enabled:bg-gray-100 duration-100 h-10 outline-none' /> - - - {!isUpdating - ?
- - + <> + + +

{name}

+ + +
+ {privileges?.map((element, index) => { + return
{element.name}
+ })}
- :
- -
- } - - + + + setModalOpen(false)} + onConfirm={handleDelete} + message={`Voulez-vous vraiment supprimer le rôle ?`} + /> + + ) } diff --git a/src/app/role/UpdateRoleForm.jsx b/src/app/role/UpdateRoleForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..e980dbf25c93bfccfd131e934585909e7ee45a26 --- /dev/null +++ b/src/app/role/UpdateRoleForm.jsx @@ -0,0 +1,143 @@ +import { useNotification } from '@/context/NotificationContext' +import React, { useState, useRef, useEffect, useMemo } from 'react' +import fetchRequest from '../lib/fetchRequest' +import Loader from '@/components/Loader/Loader' +import CancelIcon from "@/static/image/svg/cancel.svg" +import { isArray } from '../lib/TypesHelper' +const UpdateRoleForm = ({ setRoleToUpdate, setRoles, roles, privileges: rolePrivileges, name, id }) => { + const { toggleNotification } = useNotification() + const [loadingStatus, setLoadingStatus] = useState(false) + const [roleName, setRoleName] = useState(name) + const [privileges, setPrivileges] = useState(null) + const [selectedPrivileges, setSelectedPrivileges] = useState(isArray(rolePrivileges) ? rolePrivileges : []) + const inputRef = useRef(null) + console.log("les priv de role ", rolePrivileges) + useEffect(() => { + const getPrivileges = async () => { + const { data, errors, isSuccess } = await fetchRequest("/privileges") + if (isSuccess) { + setPrivileges(data) + } else { + setPrivileges([]) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + getPrivileges() + }, []) + const handleSubmit = async (event) => { + event.preventDefault() + setLoadingStatus(true) + const { isSuccess, errors, data, status } = await fetchRequest(`/roles/${id}/`, { + method: "PATCH", + body: JSON.stringify({ name: roleName, privileges: selectedPrivileges.filter((element) => privileges.find((prvElement) => prvElement.id === element.id)).map((element) => element.id) }) + }) + console.log(data) + setLoadingStatus(false) + if (isSuccess) { + setRoles((roles) => roles.map((element) => element.id === id ? data : element)) + toggleNotification({ + visible: true, + message: "Le rôle a été modifé avec succès", + type: "success" + }) + setRoleToUpdate(null) + } else { + if (errors.type === "ValidationError") { + if (errors.detail.name) { + toggleNotification({ + type: "warning", + message: "Le nom de rôle existe déjà", + visible: true, + }) + } + else { + toggleNotification({ + visible: true, + message: "Erreur de validation de rôle", + type: "warning" + }) + setRoleToUpdate(null) + } + } else if (status === 404) { + toggleNotification({ + visible: true, + message: "Le rôle n'a pas été trouvé", + type: "warning" + }) + setRoleToUpdate(null) + } else if (errors.detail === "Privilege matching query does not exist.") { + toggleNotification({ + visible: true, + message: "Des privilèges que vous avez utilisés ont été supprimés.", + type: "warning" + }) + setRoleToUpdate(null) + } + else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + setRoleToUpdate(null) + } + console.log(errors) + } + } + const handleRoleNameChange = (event) => { + setRoleName(event.target.value) + } + const handlePrivilegeClick = (privilege) => { + if (selectedPrivileges.find((element) => element.id === privilege.id)) { + setSelectedPrivileges(selectedPrivileges.filter((element) => element.id !== privilege.id)) + } else { + setSelectedPrivileges([...selectedPrivileges, privilege]) + } + } + const selectAll = () => { + if (privileges.every((element) => selectedPrivileges.find((priv) => priv.id === element.id))) + setSelectedPrivileges([]) + else setSelectedPrivileges(privileges) + } + var isAllSelected = useMemo(() => privileges ? privileges.every((element) => selectedPrivileges.find((priv) => priv.id === element.id)) : false, [selectedPrivileges, privileges]) + return ( +
+
+ setRoleToUpdate(null)} className="h-8 w-8 cursor-pointer absolute top-2 right-2 fill-neutral-600" /> +
+

Modification de Rôle

+
+ + +
+ {(privileges) ?
+
+ +
{!isAllSelected ? "Sélectionner tout" : "désélectionner"}
+
+
+ {privileges.length !== 0 ? privileges?.map((privilege) => { + const isSelected = selectedPrivileges.find((element) => element.id === privilege.id) !== undefined + return
handlePrivilegeClick(privilege)} key={privilege.id} className={`${!isSelected ? 'text-neutral-400 hover:border-neutral-400 hover:text-neutral-500 border-neutral-300 bg-neutral-100' : 'text-indigo-500 hover:border-indigo-500 hover:text-indigo-500 border-indigo-400 bg-indigo-100'} will-change-contents h-6 text-sm flex items-center justify-center duration-150 delay-75 cursor-pointer text-semibold leading-[0] border-2 py-0.5 rounded-full w-fit px-2`}>{privilege.name}
+ }) :
+

Pas encore des habilitations

+
} +
+
:
} +
+ +
+
+
+
+ ) +} + +export default UpdateRoleForm \ No newline at end of file diff --git a/src/app/role/page.jsx b/src/app/role/page.jsx index 78c99edfd1f13ef7552c2c5ecf729868dcc3cbd3..411c32f224b7080f45d8f933a48805edd67ee899 100644 --- a/src/app/role/page.jsx +++ b/src/app/role/page.jsx @@ -5,10 +5,15 @@ import Loader from '@/components/Loader/Loader' import RoleTableRows from './RoleTableRows' import fetchRequest from '../lib/fetchRequest' import { isArray } from '../lib/TypesHelper' - +import AddIcon from "@/static/image/svg/add.svg" +import UpdateRoleForm from './UpdateRoleForm' +import { useNotification } from '@/context/NotificationContext' const Role = () => { const [roles, setRoles] = useState([]) const [isLoading, setIsLoading] = useState(true) + const [openCreatePopup, setOpenCreatePopup] = useState(null) + const [roleToUpdate, setRoleToUpdate] = useState(null) + const { toggleNotification } = useNotification() useEffect(() => { const getRoles = async () => { const { data, errors, isSuccess } = await fetchRequest("/roles") @@ -34,21 +39,29 @@ const Role = () => {
- -

List des Roles

- {isLoading &&
} + {openCreatePopup && } + {roleToUpdate && } +
+

List des Roles

+ +
+ {isLoading &&
} {!isLoading && <> {(!isArray(roles) || roles?.length === 0) - ?
+ ?

Pas encore des roles

- :
+ :
+ - {roles.map((element) => { - return + {roles?.map((element) => { + return })}
RôleHabilitations Action
diff --git a/src/app/user/CreateUserForm.jsx b/src/app/user/CreateUserForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..f06c5ca134640ced18395b607c20c204dee24ca6 --- /dev/null +++ b/src/app/user/CreateUserForm.jsx @@ -0,0 +1,216 @@ +import React, { useState, useEffect } from 'react' +import Loader from '@/components/Loader/Loader' +import fetchRequest from '../lib/fetchRequest' +import { useNotification } from '@/context/NotificationContext' +import CancelIcon from "@/static/image/svg/cancel.svg" + + + + +function generateRandomPassword() { + const length = Math.floor(Math.random() * 3) + 8; // Length between 8 and 10 + const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const lowercase = 'abcdefghijklmnopqrstuvwxyz'; + const numbers = '0123456789'; + const symbols = '!@#$%^&*()_+[]{}|;:,.<>?'; + + let password = ''; + + password += uppercase[Math.floor(Math.random() * uppercase.length)]; + password += numbers[Math.floor(Math.random() * numbers.length)]; + password += symbols[Math.floor(Math.random() * symbols.length)]; + + const allCharacters = uppercase + lowercase + numbers + symbols; + + for (let i = 3; i < length; i++) { + const randomIndex = Math.floor(Math.random() * allCharacters.length); + password += allCharacters[randomIndex]; + } + + password = password.split('').sort(() => 0.5 - Math.random()).join(''); + + return password; +} +const CreateUserForm = ({ setIsOpen, appendUser }) => { + const [isLoading, setIsLoading] = useState(false) + const [selectedRole, setSelectedRole] = useState(null) + const { toggleNotification } = useNotification() + const [selectProjects, setSelectedProjects] = useState([]) + + const [roles, setRoles] = useState(null) + const [projects, setProjects] = useState(null) + useEffect(() => { + const getRoles = async () => { + const { data, errors, isSuccess } = await fetchRequest("/roles/") + if (isSuccess) { + setRoles(data) + } else { + setRoles([]) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + const getProjects = async () => { + const { isSuccess, errors, data } = await fetchRequest("/projects/"); + if (isSuccess) { + setProjects(data); + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + getRoles() + getProjects() + }, []) + const handleFieldChange = (event) => setUserData({ ...userData, [event.target.name]: event.target.value }) + + const [userData, setUserData] = useState({ email: "", password: generateRandomPassword(), first_name: "", last_name: "" }) + const handleSubmit = async (event) => { + event.preventDefault() + setIsLoading(true) + const { data, errors, isSuccess, status } = await fetchRequest("/users/", { + method: "POST", + body: JSON.stringify({ ...userData, username: userData.email, role: selectedRole.id, project_ids: selectProjects.map((element) => element.id) }) + }) + if (isSuccess) { + setIsLoading(false) + setSelectedRole(null) + appendUser(data.data) + toggleNotification({ + visible: true, + message: "Le rôle a été créé avec succès", + type: "success" + }) + setIsOpen(false) + } else { + setIsLoading(false) + if (errors.type === "ValidationError") { + if (errors.detail.name) { + toggleNotification({ + visible: true, + message: "Le rôle existe déjà", + type: "warning" + }) + } + else { + toggleNotification({ + visible: true, + message: "Erreur de validation de rôle", + type: "warning" + }) + setIsOpen(false) + } + } + else if (status === 409) { + toggleNotification({ + visible: true, + message: "role created with 2 or more same privileges", + type: "error" + }) + setIsOpen(false) + } else if (errors.detail === "Privilege matching query does not exist.") { + toggleNotification({ + visible: true, + message: "Des privilèges que vous avez utilisés ont été supprimés.", + type: "warning" + }) + setIsOpen(false) + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + setIsOpen(false) + } + console.log(errors) + } + } + const handleRoleClick = (newRole) => { + if (selectedRole?.id === newRole.id) { + setSelectedRole(null) + } else { + setSelectedRole(newRole) + } + } + const handleProjectClick = (project) => { + if (selectProjects.find((element) => element.id === project.id)) { + setSelectedProjects(selectProjects.filter((element) => element.id !== project.id)) + } else { + setSelectedProjects([...selectProjects, project]) + } + } + return ( +
+
+ setIsOpen(false)} className="h-8 w-8 cursor-pointer absolute top-2 right-2 fill-neutral-600" /> +
+

Ajout d utilisateur

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+ {(roles) ?
+
+ +
+
+ {roles.length !== 0 ? roles?.map((role) => { + const isSelected = selectedRole?.id === role.id + return
handleRoleClick(role)} key={role.id} className={`${!isSelected ? 'text-neutral-400 hover:border-neutral-400 hover:text-neutral-500 border-neutral-300 bg-neutral-100' : 'text-indigo-500 hover:border-indigo-500 hover:text-indigo-500 border-indigo-400 bg-indigo-100'} will-change-contents h-6 text-sm flex items-center justify-center duration-150 delay-75 cursor-pointer text-semibold leading-[0] border-2 py-0.5 rounded-full w-fit px-2`}> + {role.name} +
+ }) :
+

Pas encore des habilitations

+
} +
+
:
} + {(projects) ?
+
+ +
+
+ {projects.length !== 0 ? projects?.map((project) => { + const isSelected = selectProjects.find((element) => element.id === project.id) !== undefined + return
handleProjectClick(project)} key={project.id} className={`${!isSelected ? 'text-neutral-400 hover:border-neutral-400 hover:text-neutral-500 border-neutral-300 bg-neutral-100' : 'text-indigo-500 hover:border-indigo-500 hover:text-indigo-500 border-indigo-400 bg-indigo-100'} will-change-contents h-6 text-sm flex items-center justify-center duration-150 delay-75 cursor-pointer text-semibold leading-[0] border-2 py-0.5 rounded-full w-fit px-2`}> + {project.nom} +
+ }) :
+

Pas encore des projets

+
} +
+
:
} +
+ +
+
+
+
+ ) +} + +export default CreateUserForm \ No newline at end of file diff --git a/src/app/user/UpdateUserForm.jsx b/src/app/user/UpdateUserForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..d214f1851c494a1c39ed8432decfdc39e102c944 --- /dev/null +++ b/src/app/user/UpdateUserForm.jsx @@ -0,0 +1,9 @@ +import React from 'react' + +const UpdateUserForm = () => { + return ( +
UpdateUserForm
+ ) +} + +export default UpdateUserForm \ No newline at end of file diff --git a/src/app/user/UserTableRow.jsx b/src/app/user/UserTableRow.jsx new file mode 100644 index 0000000000000000000000000000000000000000..1860ee8ae70d4c6a07ffdcba015f733f2fb85490 --- /dev/null +++ b/src/app/user/UserTableRow.jsx @@ -0,0 +1,88 @@ +import React, { useState } from 'react' +import DeleteIcon from "@/static/image/svg/delete.svg" +import EditIcon from "@/static/image/svg/edit.svg" +import ConfirmationModal from '../ui/ConfirmationModal' +import { useNotification } from '@/context/NotificationContext' +import fetchRequest from '../lib/fetchRequest' + +const UserTableRow = ({ email, last_name, first_name, id, setUsers, role, projects }) => { + const { toggleNotification } = useNotification() + const [isModalOpen, setModalOpen] = useState(false); + const showDeletePopup = () => { + setModalOpen(true); + } + const handleDelete = async () => { + const { isSuccess, errors, status } = await fetchRequest(`/users/${id}/`, { method: "DELETE" }) + if (isSuccess) { + setUsers((users) => users.filter((element) => element.id !== id)) + toggleNotification({ + visible: true, + message: "L'utilisateur a été supprimé avec succès", + type: "success" + }) + } else if (status == 404) { + toggleNotification({ + visible: true, + message: "L'utilisateur n'a pas été trouvé", + type: "warning" + }) + } else if (errors.detail?.indexOf("Cannot delete some instances of model 'Role'") !== -1) { + toggleNotification({ + visible: true, + message: "Impossible de supprimer cet utilisateur car il est attribué à des utilisateurs", + type: "warning" + }) + } + else { + console.log(errors) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + setModalOpen(false) + console.log(errors) + } + return ( + <> + + +

{first_name} {last_name}

+ + +

{email}

+ + +

{role?.name || ""}

+ + +
    + {(!projects || projects.length === 0) &&

    -

    } + {projects?.map((project) => { + return
  • {project.nom}
  • + })} +
+ + +
+ + +
+ + + setModalOpen(false)} + onConfirm={handleDelete} + message={`Voulez-vous vraiment supprimer le rôle ?`} + /> + + ) +} + +export default UserTableRow \ No newline at end of file diff --git a/src/app/user/page.jsx b/src/app/user/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..ff8ef679f0d7958bb6da219df3c92ac8e5740c95 --- /dev/null +++ b/src/app/user/page.jsx @@ -0,0 +1,77 @@ +'use client'; +import React, { useEffect, useState } from 'react' +import CreateUserForm from './CreateUserForm' +import UpdateUserForm from './UpdateUserForm' +import AddIcon from "@/static/image/svg/add.svg" +import Loader from '@/components/Loader/Loader' +import fetchRequest from '../lib/fetchRequest'; +import { isArray } from '../lib/TypesHelper'; +import { useNotification } from '@/context/NotificationContext'; +import UserTableRow from './UserTableRow'; + +const UserPage = () => { + const [users, setUsers] = useState([]) + const [isLoading, setIsLoading] = useState(true) + const [openCreatePopup, setOpenCreatePopup] = useState(null) + const [userToUpdate, setUserToUpdate] = useState(null) + const { toggleNotification } = useNotification() + + useEffect(() => { + const getUsers = async () => { + const { data, errors, isSuccess } = await fetchRequest("/users") + setIsLoading(false) + if (isSuccess) { + console.log(data) + setUsers(data) + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + } + getUsers() + }, []) + const appendUser = (newUser) => { + setUsers([newUser, ...users]) + } + return (
+
+
+ {openCreatePopup && } + {userToUpdate && } +
+

List des Utilisateurs

+ +
+ {(isLoading) &&
} + {(!isLoading) && <> {(!isArray(users) || users?.length === 0) + ?
+

Pas encore des utilisateurs

+
+ :
+ + + + + + + + + {users?.map((element) => { + return + })} +
NomEmailRôleProjectsAction
+
+ }} +
+
+
+ ) +} + +export default UserPage \ No newline at end of file diff --git a/src/static/image/svg/add.svg b/src/static/image/svg/add.svg new file mode 100644 index 0000000000000000000000000000000000000000..37eaf783c6b70ff9297a84dfff632105ad288efe --- /dev/null +++ b/src/static/image/svg/add.svg @@ -0,0 +1 @@ + \ No newline at end of file