From b96cac8bc167fa167e1dcd01be987e29e80240a0 Mon Sep 17 00:00:00 2001 From: schlaifa Date: Mon, 13 Nov 2023 15:52:11 +0100 Subject: [PATCH 01/67] (hel-537) make admin page reachable for role 1 and role 2 --- .../gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts | 2 +- src/frontend/ui/commun/Header/Header.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index 6b9bd86b7..3dcefff16 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -107,7 +107,7 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { async checkIfAdmin(userId: string): Promise { const user = await (await this.orm).getRepository(UtilisateurModel).findOneBy({ code: userId.trim() }); - if (user && user.roleId === '1') { + if (user && (user.roleId === '1' || user.roleId === '2')) { return true } else return false; } diff --git a/src/frontend/ui/commun/Header/Header.tsx b/src/frontend/ui/commun/Header/Header.tsx index abd9a7e9e..baafe16ab 100644 --- a/src/frontend/ui/commun/Header/Header.tsx +++ b/src/frontend/ui/commun/Header/Header.tsx @@ -157,7 +157,7 @@ export const Header = () => { Historique - {data.user.role === '1' && ( + {(data.user.role === '1' || data.user.role === '2') && (
  • {(data.user.role === '1' || data.user.role === '2') && (
  • - +
      +
    • + +
    • +
    • + +
    • +
  • )}
  • diff --git a/src/frontend/ui/parametrage-profil/ParametragePage.tsx b/src/frontend/ui/parametrage-profil/ParametragePage.tsx index c51a591db..632eb04ea 100644 --- a/src/frontend/ui/parametrage-profil/ParametragePage.tsx +++ b/src/frontend/ui/parametrage-profil/ParametragePage.tsx @@ -15,6 +15,7 @@ export const ParametragePage = () => { const profileContext = useContext(ProfileContext); const router = useRouter(); const { getAllProfiles } = useParametrage(); + const { paths } = useDependencies(); useEffect(() => { if (data?.user.idUser) { @@ -28,7 +29,7 @@ export const ParametragePage = () => { <>

    {wording.PARAMETRAGE_TITRE}

    diff --git a/src/frontend/ui/parametrage-profil/useParametrage.ts b/src/frontend/ui/parametrage-profil/useParametrage.ts index 1cc45f75f..128cbf502 100644 --- a/src/frontend/ui/parametrage-profil/useParametrage.ts +++ b/src/frontend/ui/parametrage-profil/useParametrage.ts @@ -3,10 +3,13 @@ import { useContext } from "react"; import { ProfileValue } from "../../../../database/models/ProfilModel"; import { ProfileContext } from "../commun/contexts/ProfilContext"; +import { useDependencies } from "../commun/contexts/useDependencies"; export function useParametrage() { const profileContext = useContext(ProfileContext); const router = useRouter(); + const { paths } = useDependencies(); + const updateProfile = (userId: string, code: string, value: ProfileValue) => { fetch("/api/profile/update", { @@ -15,7 +18,7 @@ export function useParametrage() { method: "POST", }).then((response) => { if (response.status === 200) - router.push('/settings') + router.push(paths.PROFILES_LIST) }) } @@ -26,7 +29,7 @@ export function useParametrage() { method: "POST", }).then((response) => { if (response.status === 200) - router.push('/settings') + router.push(paths.PROFILES_LIST) }) } diff --git a/src/frontend/ui/parametrage-utilisateurs/usersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/usersListPage.tsx new file mode 100644 index 000000000..6a3e05900 --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/usersListPage.tsx @@ -0,0 +1,10 @@ +import "@gouvfr/dsfr/dist/component/table/table.min.css"; + +export const UsersListPage = () => { + + return ( +
    + page users +
    + ); +}; \ No newline at end of file diff --git a/src/pages/settings/add-profile.tsx b/src/pages/settings/add-profile.tsx deleted file mode 100644 index 853d22af9..000000000 --- a/src/pages/settings/add-profile.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useDependencies } from "../../frontend/ui/commun/contexts/useDependencies"; -import { useBreadcrumb } from "../../frontend/ui/commun/hooks/useBreadcrumb"; -import { NewProfileSettingsPage } from "../../frontend/ui/parametrage-profil/NewProfileSettingsPage"; - -const Parametrage = () => { - const { wording } = useDependencies(); - - useBreadcrumb([ - { - label: wording.PARAMETRAGE_NEW_PROFILE, - path: "", - }, - ]); - return ; -} - -export default Parametrage; \ No newline at end of file diff --git a/src/pages/settings/index.tsx b/src/pages/settings/index.tsx deleted file mode 100644 index bbf372462..000000000 --- a/src/pages/settings/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useDependencies } from "../../frontend/ui/commun/contexts/useDependencies"; -import { useBreadcrumb } from "../../frontend/ui/commun/hooks/useBreadcrumb"; -import { ParametragePage } from "../../frontend/ui/parametrage-profil/ParametragePage"; - -const Parametrage = () => { - const { wording } = useDependencies(); - - useBreadcrumb([ - { - label: wording.PARAMETRAGE_TITRE, - path: "", - }, - ]); - return ; -} - -export default Parametrage; \ No newline at end of file diff --git a/src/pages/settings/[profileCode].tsx b/src/pages/settings/profiles/[profileCode].tsx similarity index 77% rename from src/pages/settings/[profileCode].tsx rename to src/pages/settings/profiles/[profileCode].tsx index 615b6d30f..f218e547b 100644 --- a/src/pages/settings/[profileCode].tsx +++ b/src/pages/settings/profiles/[profileCode].tsx @@ -1,9 +1,9 @@ import { GetStaticPathsResult, GetStaticPropsResult } from "next"; -import { ProfileValue } from "../../../database/models/ProfilModel"; -import { getProfileByCodeEndpoint } from "../../backend/infrastructure/controllers/getProfileByCodeEndpoint"; -import { dependencies } from "../../backend/infrastructure/dependencies"; -import { ParametrageProfilPage } from "../../frontend/ui/parametrage-profil/ParametrageProfilPage"; +import { ProfileValue } from "../../../../database/models/ProfilModel"; +import { getProfileByCodeEndpoint } from "../../../backend/infrastructure/controllers/getProfileByCodeEndpoint"; +import { dependencies } from "../../../backend/infrastructure/dependencies"; +import { ParametrageProfilPage } from "../../../frontend/ui/parametrage-profil/ParametrageProfilPage"; type RouterProps = Readonly<{ profileValue: ProfileValue; diff --git a/src/pages/settings/profiles/add-profile.tsx b/src/pages/settings/profiles/add-profile.tsx new file mode 100644 index 000000000..8b1802a70 --- /dev/null +++ b/src/pages/settings/profiles/add-profile.tsx @@ -0,0 +1,17 @@ +import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; +import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; +import { NewProfileSettingsPage } from "../../../frontend/ui/parametrage-profil/NewProfileSettingsPage"; + +const Parametrage = () => { + const { wording } = useDependencies(); + + useBreadcrumb([ + { + label: wording.PARAMETRAGE_NEW_PROFILE, + path: "", + }, + ]); + return ; +} + +export default Parametrage; \ No newline at end of file diff --git a/src/pages/settings/profiles/index.tsx b/src/pages/settings/profiles/index.tsx new file mode 100644 index 000000000..d04b6cc6e --- /dev/null +++ b/src/pages/settings/profiles/index.tsx @@ -0,0 +1,17 @@ +import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; +import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; +import { ParametragePage } from "../../../frontend/ui/parametrage-profil/ParametragePage"; + +const Parametrage = () => { + const { wording } = useDependencies(); + + useBreadcrumb([ + { + label: wording.PARAMETRAGE_TITRE, + path: "", + }, + ]); + return ; +} + +export default Parametrage; \ No newline at end of file diff --git a/src/pages/settings/users/index.tsx b/src/pages/settings/users/index.tsx new file mode 100644 index 000000000..e1de41602 --- /dev/null +++ b/src/pages/settings/users/index.tsx @@ -0,0 +1,17 @@ +import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; +import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; +import { UsersListPage } from "../../../frontend/ui/parametrage-utilisateurs/usersListPage"; + +const ParametrageUser = () => { + const { wording } = useDependencies(); + + useBreadcrumb([ + { + label: wording.USERS_LIST, + path: "", + }, + ]); + return ; +} + +export default ParametrageUser; \ No newline at end of file From 7a63a625ef370567a001e765e8d222575e7caa12 Mon Sep 17 00:00:00 2001 From: Adolato Date: Thu, 16 Nov 2023 17:02:33 +0100 Subject: [PATCH 03/67] =?UTF-8?q?(hel-537)=20hel-537/[Profil]-=20Cr=C3=A9a?= =?UTF-8?q?tion=20console=20pour=20les=20administrateurs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuration/wording/Wording.tsx | 14 +- .../configuration/wording/WordingFr.tsx | 23 ++-- .../ui/parametrage-profil/ParametragePage.tsx | 120 +++++++++--------- .../ui/parametrage-profil/useParametrage.ts | 79 ++++++------ src/frontend/utils/dateUtils.ts | 9 +- src/pages/settings/profiles/index.tsx | 44 +++++-- 6 files changed, 152 insertions(+), 137 deletions(-) diff --git a/src/frontend/configuration/wording/Wording.tsx b/src/frontend/configuration/wording/Wording.tsx index 470e20e93..b90d3bc51 100644 --- a/src/frontend/configuration/wording/Wording.tsx +++ b/src/frontend/configuration/wording/Wording.tsx @@ -14,7 +14,6 @@ export interface Wording { readonly BACK_TO_CONNEXION: string; readonly APPLY: string; - // Messages d'erreur readonly MISSING_EMAIL: string; readonly EMAIL_NOT_VALID: string; @@ -60,11 +59,11 @@ export interface Wording { readonly EMAIL_ALREADY_USED: string; // Connexion - readonly CONNEXION_IDENTIFIANT: string - readonly CONNEXION_MOT_DE_PASSE: string - readonly CONNEXION_MOT_DE_PASSE_OUBLIE: string - readonly FORGET_PASSEWORD: string - readonly CONNEXION_LIBELLE: string + readonly CONNEXION_IDENTIFIANT: string; + readonly CONNEXION_MOT_DE_PASSE: string; + readonly CONNEXION_MOT_DE_PASSE_OUBLIE: string; + readonly FORGET_PASSEWORD: string; + readonly CONNEXION_LIBELLE: string; // Recherche readonly RECHERCHE_DESCRIPTION: ReactElement; @@ -380,9 +379,10 @@ export interface Wording { readonly CREATION_DATE: string; readonly PROFILE_CODE: string; readonly PARAMETRAGE_NEW_PROFILE: string; + readonly AJOUTER_UN_PROFIL: string; + readonly VOUS_NAVEZ_AUCUN_PROFIL: string; readonly USERS_LIST: string; - // Profile page readonly USER_PROFILE: string; readonly FIRSTNAME: string; diff --git a/src/frontend/configuration/wording/WordingFr.tsx b/src/frontend/configuration/wording/WordingFr.tsx index ee8d1638f..af82648b3 100644 --- a/src/frontend/configuration/wording/WordingFr.tsx +++ b/src/frontend/configuration/wording/WordingFr.tsx @@ -16,7 +16,6 @@ export class WordingFr implements Wording { readonly BACK_TO_CONNEXION: string = "Retour à la page de connexion"; readonly APPLY: string = "Appliquer"; - // Messages d'erreur readonly MISSING_EMAIL: string = "Veuillez renseigner le champ courriel"; readonly EMAIL_NOT_VALID: string = "Veuillez saisir une adresse email valide"; @@ -24,7 +23,6 @@ export class WordingFr implements Wording { readonly INVALID_REQUEST: string = "veuillez vérifier vos données"; readonly INVALID_USER: string = "Compte non inscrit sur Helios"; - // Header readonly INTITULÉ_RÉPUBLIQUE_FRANÇAISE: ReactElement = ( <> @@ -65,18 +63,16 @@ export class WordingFr implements Wording { // Inscription readonly REGISTRATION_PAGE_TITLE: string = "Demande d'accès à Helios"; - readonly SEND: string = 'Envoyer'; + readonly SEND: string = "Envoyer"; readonly REGISTRARTION_SUCCESS_MESSAGE: string = "Un courriel a été envoyé à votre adresse email."; readonly EMAIL_ALREADY_USED: string = "L'adresse mail saisie est déjà rattachée à un compte. Si vous avez oublié votre mot de passe, cliquez "; - // Connexion - readonly CONNEXION_IDENTIFIANT: string = "Identifiant *" - readonly CONNEXION_MOT_DE_PASSE: string = "Mot de passe *" - readonly CONNEXION_MOT_DE_PASSE_OUBLIE: string = "Vous n'avez pas de compte ? " - readonly FORGET_PASSEWORD: string = "Mot de passe oublié ?" - readonly CONNEXION_LIBELLE: string = "Connexion" - + readonly CONNEXION_IDENTIFIANT: string = "Identifiant *"; + readonly CONNEXION_MOT_DE_PASSE: string = "Mot de passe *"; + readonly CONNEXION_MOT_DE_PASSE_OUBLIE: string = "Vous n'avez pas de compte ? "; + readonly FORGET_PASSEWORD: string = "Mot de passe oublié ?"; + readonly CONNEXION_LIBELLE: string = "Connexion"; // Recherche readonly RECHERCHE_DESCRIPTION: ReactElement = ( @@ -458,7 +454,7 @@ export class WordingFr implements Wording { readonly REINITIALISATION_MOT_PASSE_TITRE: string = "Réinitialisation de votre mot de passe"; readonly REINITIALISATION_MOT_PASSE_DESCRIPTION: string = "Merci de renseigner votre nouveau mot de passe"; readonly DIFFERENT_MOT_PASSE: string = "Le mot de passe doit être différent du mot de passe actuel"; - readonly WRONG_OLD_MOT_DE_PASSE: string = "Ancien mot de passe erroné" + readonly WRONG_OLD_MOT_DE_PASSE: string = "Ancien mot de passe erroné"; readonly PARAMETRAGE_TITRE: string = "Liste des profils"; readonly PARAMETRAGE_PROFILE: string = "Paramétrage de profil: "; @@ -469,9 +465,11 @@ export class WordingFr implements Wording { readonly PARAMETRAGE_AUTRE_REGION: string = "Autre région"; readonly CREATION_DATE: string = "Date de création"; readonly PROFILE_CODE: string = "Code de profil"; + readonly AJOUTER_UN_PROFIL: string = "Ajouter un profil"; readonly PARAMETRAGE_NEW_PROFILE: string = "Ajouter un nouveau profil"; - readonly USERS_LIST: string = "Liste des utilisateurs"; + readonly VOUS_NAVEZ_AUCUN_PROFIL: string = "Vous n'avez aucun profil"; + readonly USERS_LIST: string = "Liste des utilisateurs"; // Profile page readonly USER_PROFILE: string = "Profil de l'utilisateur"; @@ -484,5 +482,4 @@ export class WordingFr implements Wording { readonly ADMIN: string = "Administrateur régional ou en administration centrale"; readonly USER: string = "Utilisateur"; readonly PROFILE: string = "Profil"; - } diff --git a/src/frontend/ui/parametrage-profil/ParametragePage.tsx b/src/frontend/ui/parametrage-profil/ParametragePage.tsx index 632eb04ea..d425f44c3 100644 --- a/src/frontend/ui/parametrage-profil/ParametragePage.tsx +++ b/src/frontend/ui/parametrage-profil/ParametragePage.tsx @@ -1,72 +1,68 @@ import "@gouvfr/dsfr/dist/component/table/table.min.css"; -import { useSession } from "next-auth/react"; import { useRouter } from "next/router"; -import { useContext, useEffect } from "react"; import { formatDateAndHours } from "../../utils/dateUtils"; -import { ProfileContext } from "../commun/contexts/ProfilContext"; import { useDependencies } from "../commun/contexts/useDependencies"; import styles from "./Parametrage.module.css"; -import { useParametrage } from "./useParametrage"; -export const ParametragePage = () => { - const { wording } = useDependencies(); - const { data } = useSession(); - const profileContext = useContext(ProfileContext); - const router = useRouter(); - const { getAllProfiles } = useParametrage(); - const { paths } = useDependencies(); +export const ParametragePage = ({ profiles }: any) => { + const { wording } = useDependencies(); + const router = useRouter(); - useEffect(() => { - if (data?.user.idUser) { - getAllProfiles(data.user.idUser); - } - }, [data]); + const { paths } = useDependencies(); - return ( -
    - {profileContext?.profiles && ( - <> -

    {wording.PARAMETRAGE_TITRE}

    - + return ( +
    + {profiles && ( + <> +

    {wording.PARAMETRAGE_TITRE}

    + - {profileContext?.profiles.length === 0 ? (
    Vous n'avez aucun profil
    ) : ( -
    - - - - - - - - - - {profileContext?.profiles.map((profile: any) => ( - - - - - - ))} - -
    {wording.PROFILE}{wording.PROFILE_CODE}{wording.CREATION_DATE}
    - - {profile.label} - - - {profile.code} {formatDateAndHours(profile.dateCreation)}
    -
    - ) - } - - )} -
    - ); -}; \ No newline at end of file + {profiles.length === 0 ? ( +
    {wording.VOUS_NAVEZ_AUCUN_PROFIL}
    + ) : ( +
    + + + + + + + + + + {profiles.map((profile: any) => ( + + + + + + ))} + +
    {wording.PROFILE}{wording.PROFILE_CODE}{wording.CREATION_DATE}
    + + {profile.label} + + + {profile.code}{" "} + {formatDateAndHours(profile.dateCreation)}
    +
    + )} + + )} +
    + ); +}; diff --git a/src/frontend/ui/parametrage-profil/useParametrage.ts b/src/frontend/ui/parametrage-profil/useParametrage.ts index 128cbf502..58d448d5d 100644 --- a/src/frontend/ui/parametrage-profil/useParametrage.ts +++ b/src/frontend/ui/parametrage-profil/useParametrage.ts @@ -6,48 +6,45 @@ import { ProfileContext } from "../commun/contexts/ProfilContext"; import { useDependencies } from "../commun/contexts/useDependencies"; export function useParametrage() { - const profileContext = useContext(ProfileContext); - const router = useRouter(); - const { paths } = useDependencies(); + const profileContext = useContext(ProfileContext); + const router = useRouter(); + const { paths } = useDependencies(); + const updateProfile = (userId: string, code: string, value: ProfileValue) => { + fetch("/api/profile/update", { + body: JSON.stringify({ userId, code, value }), + headers: { "Content-Type": "application/json" }, + method: "POST", + }).then((response) => { + if (response.status === 200) router.push(paths.PROFILES_LIST); + }); + }; - const updateProfile = (userId: string, code: string, value: ProfileValue) => { - fetch("/api/profile/update", { - body: JSON.stringify({ userId, code, value }), - headers: { "Content-Type": "application/json" }, - method: "POST", - }).then((response) => { - if (response.status === 200) - router.push(paths.PROFILES_LIST) - }) - } + const saveProfile = (userId: string, label: string, profile: ProfileValue) => { + fetch("/api/profile/add", { + body: JSON.stringify({ userId, label, value: profile }), + headers: { "Content-Type": "application/json" }, + method: "POST", + }).then((response) => { + if (response.status === 200) router.push(paths.PROFILES_LIST); + }); + }; - const saveProfile = (userId: string, label: string, profile: ProfileValue) => { - fetch("/api/profile/add", { - body: JSON.stringify({ userId, label, value: profile }), - headers: { "Content-Type": "application/json" }, - method: "POST", - }).then((response) => { - if (response.status === 200) - router.push(paths.PROFILES_LIST) - }) - } + const getAllProfiles = (userId: string) => { + const params = { userId: userId }; + fetch("/api/profile/get/?" + new URLSearchParams(params).toString(), { + headers: { "Content-Type": "application/json" }, + method: "GET", + }) + .then((response) => response.json()) + .then((data) => { + profileContext?.setProfiles(data.response); + }); + }; - const getAllProfiles = (userId: string) => { - const params = { userId: userId }; - fetch("/api/profile/get/?" + (new URLSearchParams(params)).toString(), { - headers: { "Content-Type": "application/json" }, - method: "GET", - }) - .then((response) => response.json()) - .then((data) => { - profileContext?.setProfiles(data.response); - }) - } - - return { - getAllProfiles, - saveProfile, - updateProfile - }; -} \ No newline at end of file + return { + getAllProfiles, + saveProfile, + updateProfile, + }; +} diff --git a/src/frontend/utils/dateUtils.ts b/src/frontend/utils/dateUtils.ts index 57f770c82..1d2c17f79 100644 --- a/src/frontend/utils/dateUtils.ts +++ b/src/frontend/utils/dateUtils.ts @@ -15,10 +15,11 @@ export function annéesManquantes(années: (number | string)[], annéesTotales: // format DD/MM/AAAA - HHhMM export function formatDateAndHours(date: string): string { const formated = new Date(date).toLocaleDateString("fr-FR", { - day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", + day: "2-digit", + month: "2-digit", + year: "numeric", + hour: "2-digit", minute: "2-digit", }); - return (formated.replace(':', 'h').replace(' ', ' - ')); + return formated.replace(":", "h").replace(" ", " - ").replace(",", ""); } - - diff --git a/src/pages/settings/profiles/index.tsx b/src/pages/settings/profiles/index.tsx index d04b6cc6e..8e59105f2 100644 --- a/src/pages/settings/profiles/index.tsx +++ b/src/pages/settings/profiles/index.tsx @@ -1,17 +1,41 @@ +import { GetServerSidePropsContext, GetStaticPropsResult } from "next"; +import { getSession } from "next-auth/react"; +import { dependencies } from "../../../backend/infrastructure/dependencies"; + import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; + +import { getAllProfilesEndpoint } from "../../../backend/infrastructure/controllers/getAllProfilesEndpoint"; import { ParametragePage } from "../../../frontend/ui/parametrage-profil/ParametragePage"; -const Parametrage = () => { - const { wording } = useDependencies(); +type RouterProps = Readonly<{ profiles: any }>; + +export default function Router({ profiles }: RouterProps) { + const { wording } = useDependencies(); - useBreadcrumb([ - { - label: wording.PARAMETRAGE_TITRE, - path: "", - }, - ]); - return ; + useBreadcrumb([ + { + label: wording.PARAMETRAGE_TITRE, + path: "", + }, + ]); + + return ; } -export default Parametrage; \ No newline at end of file +export async function getServerSideProps(context: GetServerSidePropsContext): Promise> { + try { + if (true) { + const profiles = await getAllProfilesEndpoint(dependencies); + return { + props: { profiles: JSON.parse(JSON.stringify(profiles)) }, + }; + } else { + return { + notFound: true, + }; + } + } catch (error) { + throw error; + } +} From d008aace7ae2d874da7d2ed75d00775473ba4cbd Mon Sep 17 00:00:00 2001 From: Adolato Date: Thu, 16 Nov 2023 17:17:05 +0100 Subject: [PATCH 04/67] =?UTF-8?q?(hel-537)=20hel-537/[Profil]-=20Cr=C3=A9a?= =?UTF-8?q?tion=20console=20pour=20les=20administrateurs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/ui/parametrage-profil/ParametragePage.tsx | 8 ++++++-- src/pages/settings/profiles/index.tsx | 10 ++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/frontend/ui/parametrage-profil/ParametragePage.tsx b/src/frontend/ui/parametrage-profil/ParametragePage.tsx index d425f44c3..11317d430 100644 --- a/src/frontend/ui/parametrage-profil/ParametragePage.tsx +++ b/src/frontend/ui/parametrage-profil/ParametragePage.tsx @@ -1,14 +1,18 @@ import "@gouvfr/dsfr/dist/component/table/table.min.css"; import { useRouter } from "next/router"; +import { ProfilModel } from "../../../../database/models/ProfilModel"; import { formatDateAndHours } from "../../utils/dateUtils"; import { useDependencies } from "../commun/contexts/useDependencies"; import styles from "./Parametrage.module.css"; -export const ParametragePage = ({ profiles }: any) => { +type ParametragePageProps = Readonly<{ + profiles: ProfilModel[]; +}>; + +export const ParametragePage = ({ profiles }: ParametragePageProps) => { const { wording } = useDependencies(); const router = useRouter(); - const { paths } = useDependencies(); return ( diff --git a/src/pages/settings/profiles/index.tsx b/src/pages/settings/profiles/index.tsx index 8e59105f2..bb326c68d 100644 --- a/src/pages/settings/profiles/index.tsx +++ b/src/pages/settings/profiles/index.tsx @@ -1,11 +1,9 @@ -import { GetServerSidePropsContext, GetStaticPropsResult } from "next"; -import { getSession } from "next-auth/react"; -import { dependencies } from "../../../backend/infrastructure/dependencies"; +import { GetStaticPropsResult } from "next"; +import { getAllProfilesEndpoint } from "../../../backend/infrastructure/controllers/getAllProfilesEndpoint"; +import { dependencies } from "../../../backend/infrastructure/dependencies"; import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; - -import { getAllProfilesEndpoint } from "../../../backend/infrastructure/controllers/getAllProfilesEndpoint"; import { ParametragePage } from "../../../frontend/ui/parametrage-profil/ParametragePage"; type RouterProps = Readonly<{ profiles: any }>; @@ -23,7 +21,7 @@ export default function Router({ profiles }: RouterProps) { return ; } -export async function getServerSideProps(context: GetServerSidePropsContext): Promise> { +export async function getServerSideProps(): Promise> { try { if (true) { const profiles = await getAllProfilesEndpoint(dependencies); From 722db11003258dbd9b9c410f152e03dd03227e38 Mon Sep 17 00:00:00 2001 From: Adolato Date: Mon, 20 Nov 2023 15:55:29 +0100 Subject: [PATCH 05/67] (hel-537) hel-537/page-admin --- database/models/UtilisateurModel.ts | 15 +- .../controllers/getUserByCodeEndpoint.ts | 13 + .../getUsersListPaginatedEndpoint.ts | 13 + .../TypeOrmUtilisateurLoader.ts | 250 +++++++++------- .../gateways/UtilisateurLoader.ts" | 5 +- .../use-cases/ProfilesUseCase.ts" | 28 +- .../use-cases/UtilisateursUseCase.ts" | 14 + .../configuration/wording/Wording.tsx | 9 + .../configuration/wording/WordingFr.tsx | 9 + .../parametrage-profil/ParamatrageTable.tsx | 147 ++++++---- .../EditUser/EditUser.module.css | 13 + .../EditUser/EditUser.tsx | 161 +++++++++++ .../UsersListPage/UsersListPage.module.css | 69 +++++ .../UsersListPage/UsersListPage.tsx | 268 ++++++++++++++++++ .../usersListPage.tsx | 10 - src/frontend/ui/profile/ProfilePage.tsx | 116 +++----- src/pages/settings/profiles/index.tsx | 17 +- src/pages/settings/users/[userCode].tsx | 60 ++++ src/pages/settings/users/index.tsx | 38 ++- 19 files changed, 966 insertions(+), 289 deletions(-) create mode 100644 src/backend/infrastructure/controllers/getUserByCodeEndpoint.ts create mode 100644 src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts create mode 100644 "src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" create mode 100644 src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.module.css create mode 100644 src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.tsx create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx delete mode 100644 src/frontend/ui/parametrage-utilisateurs/usersListPage.tsx create mode 100644 src/pages/settings/users/[userCode].tsx diff --git a/database/models/UtilisateurModel.ts b/database/models/UtilisateurModel.ts index 67d4372f2..f7deeeeab 100644 --- a/database/models/UtilisateurModel.ts +++ b/database/models/UtilisateurModel.ts @@ -1,14 +1,4 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, - ManyToOne, - JoinColumn, - BeforeInsert, - BeforeUpdate, -} from "typeorm"; +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn, BeforeInsert, BeforeUpdate } from "typeorm"; import { InstitutionModel } from "./InstitutionModel"; import { RoleModel } from "./RoleModel"; @@ -40,6 +30,9 @@ export class UtilisateurModel { @JoinColumn({ name: "ut_institution", referencedColumnName: "id" }) public institution!: InstitutionModel; + @Column({ name: "ut_institution" }) + public institution2!: number; + @Column({ name: "ut_actif", default: false }) public actif!: boolean; diff --git a/src/backend/infrastructure/controllers/getUserByCodeEndpoint.ts b/src/backend/infrastructure/controllers/getUserByCodeEndpoint.ts new file mode 100644 index 000000000..156c3a6a4 --- /dev/null +++ b/src/backend/infrastructure/controllers/getUserByCodeEndpoint.ts @@ -0,0 +1,13 @@ +import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; +import { UtilisateursUseCase } from "../../métier/use-cases/UtilisateursUseCase"; +import { Dependencies } from "../dependencies"; + +export async function getUserByCodeEndpoint(dependencies: Dependencies, code: string): Promise { + try { + const UtilisateurUseCase = new UtilisateursUseCase(dependencies.utilisateurLoader); + return await UtilisateurUseCase.getUserByCode(code); + } catch (error) { + dependencies.logger.error(error); + throw error; + } +} diff --git a/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts b/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts new file mode 100644 index 000000000..295f56b84 --- /dev/null +++ b/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts @@ -0,0 +1,13 @@ +import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; +import { UtilisateursUseCase } from "../../métier/use-cases/UtilisateursUseCase"; +import { Dependencies } from "../dependencies"; + +export async function getUsersListPaginatedEndpoint(dependencies: Dependencies, key: string, sort: string, pdescrtion: number): Promise { + try { + const UtilisateurUseCase = new UtilisateursUseCase(dependencies.utilisateurLoader); + return await UtilisateurUseCase.getUsersListPaginated(key, sort, pdescrtion); + } catch (error) { + dependencies.logger.error(error); + throw error; + } +} diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index 3dcefff16..912241b36 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -1,88 +1,91 @@ -import { compare, genSalt, hash } from 'bcrypt'; -import { createHash } from 'crypto'; -import fs from 'fs'; +import { compare, genSalt, hash } from "bcrypt"; +import { createHash } from "crypto"; +import fs from "fs"; import path from "path"; -import { DataSource } from "typeorm"; +import { DataSource, Like } from "typeorm"; -import { InstitutionModel } from '../../../../../database/models/InstitutionModel'; -import { ProfilModel } from '../../../../../database/models/ProfilModel'; -import { RoleModel } from '../../../../../database/models/RoleModel'; +import { InstitutionModel } from "../../../../../database/models/InstitutionModel"; +import { ProfilModel } from "../../../../../database/models/ProfilModel"; +import { RoleModel } from "../../../../../database/models/RoleModel"; import { UtilisateurModel } from "../../../../../database/models/UtilisateurModel"; -import { generateToken } from '../../../jwtHelper'; -import { Institution } from '../../../métier/entities/Utilisateur/Institution'; +import { generateToken } from "../../../jwtHelper"; +import { Institution } from "../../../métier/entities/Utilisateur/Institution"; import { RésultatLogin } from "../../../métier/entities/Utilisateur/RésultatLogin"; import { UtilisateurLoader } from "../../../métier/gateways/UtilisateurLoader"; -import { sendEmail } from '../../../sendEmail'; - - +import { sendEmail } from "../../../sendEmail"; export class TypeOrmUtilisateurLoader implements UtilisateurLoader { - constructor(private readonly orm: Promise) { } - - async login(email: string, password: string): Promise { - const user = await (await this.orm).getRepository(UtilisateurModel).findOne({ where: { email: email.trim().toLowerCase() }, relations: ['institution'] }); - if (user) { - const hashing = createHash('sha256'); - hashing.update(password); - const hashedPassword = hashing.digest('hex'); - return await compare(password, user.password) || hashedPassword === user.password ? { utilisateur: user } : null - } else { - return null - } - } - - async checkIfEmailExists(email: string): Promise { - const user = await (await this.orm).getRepository(UtilisateurModel).findOneBy({ email: email.trim().toLowerCase() }); - if (user) { - return true - } else return false; - } - - async getInstitutions(): Promise { - const institutions = await (await this.orm).getRepository(InstitutionModel).find(); - return institutions; + constructor(private readonly orm: Promise) {} + async getUserByCode(code: string): Promise { + return await (await this.orm).getRepository(UtilisateurModel).findOne({ where: { code: code } }); + } + + async login(email: string, password: string): Promise { + const user = await (await this.orm).getRepository(UtilisateurModel).findOne({ where: { email: email.trim().toLowerCase() }, relations: ["institution"] }); + if (user) { + const hashing = createHash("sha256"); + hashing.update(password); + const hashedPassword = hashing.digest("hex"); + return (await compare(password, user.password)) || hashedPassword === user.password ? { utilisateur: user } : null; + } else { + return null; } - - async createAccount(firstName: string, lastName: string, email: string, institution: string): Promise { - try { - const account = new UtilisateurModel(); - - const institutionToSave = await (await this.orm).getRepository(InstitutionModel).findOneBy({ code: institution }); - const roleToSave = await (await this.orm).getRepository(RoleModel).findOneBy({ code: 'USER' }); - const profileToSave = await (await this.orm).getRepository(ProfilModel).findOneBy({ id: 1 }); - - const passwordToSave = 'HeliosConnect-' + institutionToSave?.codeGeo; - - const salt = await genSalt(10); - const hashedPassword = await hash(passwordToSave, salt); - - if (institutionToSave && roleToSave && profileToSave) { - account.nom = lastName; - account.prenom = firstName; - account.email = email; - account.institution = institutionToSave; - account.role = roleToSave; - account.password = hashedPassword; - account.profils = [profileToSave.code]; - account.actif = true; - account.dateCreation = new Date(); - } - - (await this.orm).getRepository(UtilisateurModel).save(account) - .then(async () => { - const absolutePath = path.resolve(process.cwd(), './public/logo-helios.png'); - const imageContent = fs.readFileSync(absolutePath, 'base64'); - const APP_URL = process.env["APP_BASE_URL"]; - const token = generateToken(email, '24h'); - const images = [ - { - "contentType": "image/png", - "filename": "logo-helios", - "content": imageContent, - "contentId": "logo" - } - ]; - const body = ` + } + + async checkIfEmailExists(email: string): Promise { + const user = await (await this.orm).getRepository(UtilisateurModel).findOneBy({ email: email.trim().toLowerCase() }); + if (user) { + return true; + } else return false; + } + + async getInstitutions(): Promise { + const institutions = await (await this.orm).getRepository(InstitutionModel).find(); + return institutions; + } + + async createAccount(firstName: string, lastName: string, email: string, institution: string): Promise { + try { + const account = new UtilisateurModel(); + + const institutionToSave = await (await this.orm).getRepository(InstitutionModel).findOneBy({ code: institution }); + const roleToSave = await (await this.orm).getRepository(RoleModel).findOneBy({ code: "USER" }); + const profileToSave = await (await this.orm).getRepository(ProfilModel).findOneBy({ id: 1 }); + + const passwordToSave = "HeliosConnect-" + institutionToSave?.codeGeo; + + const salt = await genSalt(10); + const hashedPassword = await hash(passwordToSave, salt); + + if (institutionToSave && roleToSave && profileToSave) { + account.nom = lastName; + account.prenom = firstName; + account.email = email; + account.institution = institutionToSave; + account.role = roleToSave; + account.password = hashedPassword; + account.profils = [profileToSave.code]; + account.actif = true; + account.dateCreation = new Date(); + } + + (await this.orm) + .getRepository(UtilisateurModel) + .save(account) + .then(async () => { + const absolutePath = path.resolve(process.cwd(), "./public/logo-helios.png"); + const imageContent = fs.readFileSync(absolutePath, "base64"); + const APP_URL = process.env["APP_BASE_URL"]; + const token = generateToken(email, "24h"); + const images = [ + { + contentType: "image/png", + filename: "logo-helios", + content: imageContent, + contentId: "logo", + }, + ]; + const body = ` helios

    Bonjour,

    L'équipe projet Helios est heureuse de vous accueillir sur l'application Helios. Pour finaliser la création de votre compte, merci de cliquer @@ -92,31 +95,72 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader {

    L'équipe Helios reste disponible à l'adresse mail suivante : dnum.scn-helios-support@sg.social.gouv.fr

    Cordialement,

    L'équipe Helios

    `; - sendEmail(email, "[Helios]-Création de votre compte Helios", body, images); - }) - .catch((error) => { - // eslint-disable-next-line no-console - console.log("error", error); - }); - - } catch (error) { - // eslint-disable-next-line no-console - console.log("error", error); - } + sendEmail(email, "[Helios]-Création de votre compte Helios", body, images); + }) + .catch((error) => { + // eslint-disable-next-line no-console + console.log("error", error); + }); + } catch (error) { + // eslint-disable-next-line no-console + console.log("error", error); } - - async checkIfAdmin(userId: string): Promise { - const user = await (await this.orm).getRepository(UtilisateurModel).findOneBy({ code: userId.trim() }); - if (user && (user.roleId === '1' || user.roleId === '2')) { - return true - } else return false; - } - - async getUserProfiles(codes: string[]): Promise { - const profiles = await (await this.orm).getRepository(ProfilModel) - .createQueryBuilder("profiles") - .where('profiles.profil_code IN (:...codes)', { codes }) - .getMany(); - return profiles; + } + + async checkIfAdmin(userId: string): Promise { + const user = await (await this.orm).getRepository(UtilisateurModel).findOneBy({ code: userId.trim() }); + if (user && (user.roleId === "1" || user.roleId === "2")) { + return true; + } else return false; + } + + async getUserProfiles(codes: string[]): Promise { + const profiles = await (await this.orm) + .getRepository(ProfilModel) + .createQueryBuilder("profiles") + .where("profiles.profil_code IN (:...codes)", { codes }) + .getMany(); + return profiles; + } + + async getUsersListPaginated(key: string, sort: string, pdescrtion: number): Promise { + // return await (await this.orm).getRepository(UtilisateurModel).find(); + + const utilisateurRepo = (await this.orm).getRepository(UtilisateurModel); + + let options = {}; + + if (key) { + options = { + ...options, + where: [{ nom: Like("%" + key.toString() + "%") }, { prenom: Like("%" + key.toString() + "%") }, { email: Like("%" + key.toString() + "%") }], + }; } -} \ No newline at end of file + /* + if (sort) { + options = { + ...options, + order: { + libelle: sort.toString().toUpperCase(), + }, + }; + }*/ + + const pdescrtionA: number = parseInt(pdescrtion as any) || 1; + const take = 5; + const total = await utilisateurRepo.count(); + + const data = await utilisateurRepo.find({ + ...options, + take, + skip: (pdescrtionA - 1) * take, + }); + + return { + data, + total, + pdescrtionA, + last_pdescrtion: Math.ceil(total / take), + }; + } +} diff --git "a/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" "b/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" index dbdeca302..f1b2fe44c 100644 --- "a/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" +++ "b/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" @@ -1,4 +1,5 @@ import { ProfilModel } from "../../../../database/models/ProfilModel"; +import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; import { Institution } from "../entities/Utilisateur/Institution"; import { RésultatLogin } from "../entities/Utilisateur/RésultatLogin"; @@ -8,5 +9,7 @@ export interface UtilisateurLoader { getInstitutions(): Promise; createAccount(firstName: string, lastName: string, email: string, institution: string): Promise; getUserProfiles(codes: string[]): Promise; - checkIfAdmin(userId: string): Promise + checkIfAdmin(userId: string): Promise; + getUsersListPaginated(key: string, sort: string, pdescrtion: number): Promise; + getUserByCode(code: string): Promise; } diff --git "a/src/backend/m\303\251tier/use-cases/ProfilesUseCase.ts" "b/src/backend/m\303\251tier/use-cases/ProfilesUseCase.ts" index d4a275495..3a4f1174b 100644 --- "a/src/backend/m\303\251tier/use-cases/ProfilesUseCase.ts" +++ "b/src/backend/m\303\251tier/use-cases/ProfilesUseCase.ts" @@ -2,21 +2,21 @@ import { ProfilModel, ProfileValue } from "../../../../database/models/ProfilMod import { ProfileLoader } from "../gateways/ProfileLoader"; export class ProfilesUseCase { - constructor(private profileLoader: ProfileLoader) { } + constructor(private profileLoader: ProfileLoader) {} - async getAllProfiles(): Promise { - return await this.profileLoader.getAllProfiles(); - } + async getAllProfiles(): Promise { + return await this.profileLoader.getAllProfiles(); + } - async getProfileByCode(code: string): Promise { - return await this.profileLoader.getProfileByCode(code); - } + async getProfileByCode(code: string): Promise { + return await this.profileLoader.getProfileByCode(code); + } - async updateProfile(code: string, value: ProfileValue): Promise { - return await this.profileLoader.updateProfileValue(code, value); - } + async updateProfile(code: string, value: ProfileValue): Promise { + return await this.profileLoader.updateProfileValue(code, value); + } - async addNewProfile(label: string, value: ProfileValue): Promise { - return await this.profileLoader.addNewProfile(label, value); - } -} \ No newline at end of file + async addNewProfile(label: string, value: ProfileValue): Promise { + return await this.profileLoader.addNewProfile(label, value); + } +} diff --git "a/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" "b/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" new file mode 100644 index 000000000..43609ae51 --- /dev/null +++ "b/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" @@ -0,0 +1,14 @@ +import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; +import { UtilisateurLoader } from "../gateways/UtilisateurLoader"; + +export class UtilisateursUseCase { + constructor(private utilisateurLoader: UtilisateurLoader) {} + + async getUsersListPaginated(key: string, sort: string, pdescrtion: number): Promise { + return await this.utilisateurLoader.getUsersListPaginated(key, sort, pdescrtion); + } + + async getUserByCode(code: string): Promise { + return await this.utilisateurLoader.getUserByCode(code); + } +} diff --git a/src/frontend/configuration/wording/Wording.tsx b/src/frontend/configuration/wording/Wording.tsx index b90d3bc51..a689cf844 100644 --- a/src/frontend/configuration/wording/Wording.tsx +++ b/src/frontend/configuration/wording/Wording.tsx @@ -394,4 +394,13 @@ export interface Wording { readonly ADMIN: string; readonly USER: string; readonly PROFILE: string; + + // Utilisateur page + readonly STATUS: string; + readonly MODIFICATION_DATE: string; + readonly PAGE_UTILISATEUR_TITRE: string; + readonly AUCUN_ELEMENT_TROUVE: string; + readonly ROLE_: string; + readonly INSTITUTION: string; + readonly PAGE_EDIT_UTILISATEUR_TITRE: string; } diff --git a/src/frontend/configuration/wording/WordingFr.tsx b/src/frontend/configuration/wording/WordingFr.tsx index af82648b3..e33e04340 100644 --- a/src/frontend/configuration/wording/WordingFr.tsx +++ b/src/frontend/configuration/wording/WordingFr.tsx @@ -482,4 +482,13 @@ export class WordingFr implements Wording { readonly ADMIN: string = "Administrateur régional ou en administration centrale"; readonly USER: string = "Utilisateur"; readonly PROFILE: string = "Profil"; + + // Utilisateur page + readonly STATUS: string = "Status"; + readonly MODIFICATION_DATE: string = "Date de modification"; + readonly AUCUN_ELEMENT_TROUVE: string = "Aucun élément trouvé"; + readonly ROLE_: string = "Rôle"; + readonly PAGE_UTILISATEUR_TITRE: string = "Liste des utilisateurs"; + readonly INSTITUTION: string = "Institution"; + readonly PAGE_EDIT_UTILISATEUR_TITRE: string = "Modifier utilisateur"; } diff --git a/src/frontend/ui/parametrage-profil/ParamatrageTable.tsx b/src/frontend/ui/parametrage-profil/ParamatrageTable.tsx index bd0c32859..f3876910e 100644 --- a/src/frontend/ui/parametrage-profil/ParamatrageTable.tsx +++ b/src/frontend/ui/parametrage-profil/ParamatrageTable.tsx @@ -7,67 +7,106 @@ import { ProfileTabContent } from "./ProfileTabContent"; import { useParametrage } from "./useParametrage"; type ProfileTableProps = Readonly<{ - codeValue: string, - profileValue: ProfileValue; - creating: boolean; + codeValue: string; + profileValue: ProfileValue; + creating: boolean; }>; export const ProfileTable = ({ codeValue, profileValue, creating }: ProfileTableProps) => { - const { wording } = useDependencies(); - const { data } = useSession(); - const [userId, setUserId] = useState(''); + const { wording } = useDependencies(); + const { data } = useSession(); + const [userId, setUserId] = useState(""); - const { updateProfile, saveProfile } = useParametrage(); - const [editableInstitutionEJValues, setEditableInstitutionEJValues] = useState(profileValue.institution.profilEJ); - const [editableAutreRegionEJValues, setEditableAutreRegionEJValues] = useState(profileValue.autreRegion.profilEJ); + const { updateProfile, saveProfile } = useParametrage(); + const [editableInstitutionEJValues, setEditableInstitutionEJValues] = useState(profileValue.institution.profilEJ); + const [editableAutreRegionEJValues, setEditableAutreRegionEJValues] = useState(profileValue.autreRegion.profilEJ); - const [editableInstitutionETMSValues, setEditableInstitutionETMSValues] = useState(profileValue.institution.profilMédicoSocial); - const [editableAutreRegionETMSValues, setEditableAutreRegionETMSValues] = useState(profileValue.autreRegion.profilMédicoSocial); + const [editableInstitutionETMSValues, setEditableInstitutionETMSValues] = useState(profileValue.institution.profilMédicoSocial); + const [editableAutreRegionETMSValues, setEditableAutreRegionETMSValues] = useState(profileValue.autreRegion.profilMédicoSocial); - const [editableInstitutionETSANValues, setEditableInstitutionETSANValues] = useState(profileValue.institution.profilETSanitaire); - const [editableAutreRegionETSANValues, setEditableAutreRegionETSANValues] = useState(profileValue.autreRegion.profilETSanitaire); + const [editableInstitutionETSANValues, setEditableInstitutionETSANValues] = useState(profileValue.institution.profilETSanitaire); + const [editableAutreRegionETSANValues, setEditableAutreRegionETSANValues] = useState(profileValue.autreRegion.profilETSanitaire); - useEffect(() => { - if (data) { - setUserId(data.user.idUser); - } - }, [data]) - const saveButtonClick = () => { - if (creating) { - saveProfile(userId, codeValue, { institution: { profilEJ: editableInstitutionEJValues, profilMédicoSocial: editableInstitutionETMSValues, profilETSanitaire: editableInstitutionETSANValues }, autreRegion: { profilEJ: editableAutreRegionEJValues, profilMédicoSocial: editableAutreRegionETMSValues, profilETSanitaire: editableAutreRegionETSANValues } }) - } else { - updateProfile(userId, codeValue, { institution: { profilEJ: editableInstitutionEJValues, profilMédicoSocial: editableInstitutionETMSValues, profilETSanitaire: editableInstitutionETSANValues }, autreRegion: { profilEJ: editableAutreRegionEJValues, profilMédicoSocial: editableAutreRegionETMSValues, profilETSanitaire: editableAutreRegionETSANValues } }) - } + useEffect(() => { + if (data) { + setUserId(data.user.idUser); } + }, [data]); + const saveButtonClick = () => { + if (creating) { + saveProfile(userId, codeValue, { + institution: { + profilEJ: editableInstitutionEJValues, + profilMédicoSocial: editableInstitutionETMSValues, + profilETSanitaire: editableInstitutionETSANValues, + }, + autreRegion: { + profilEJ: editableAutreRegionEJValues, + profilMédicoSocial: editableAutreRegionETMSValues, + profilETSanitaire: editableAutreRegionETSANValues, + }, + }); + } else { + updateProfile(userId, codeValue, { + institution: { + profilEJ: editableInstitutionEJValues, + profilMédicoSocial: editableInstitutionETMSValues, + profilETSanitaire: editableInstitutionETSANValues, + }, + autreRegion: { + profilEJ: editableAutreRegionEJValues, + profilMédicoSocial: editableAutreRegionETMSValues, + profilETSanitaire: editableAutreRegionETSANValues, + }, + }); + } + }; - return ( -
    -
    -
      -
    • - -
    • -
    • - -
    • -
    • - -
    • -
    - - - -
    - -
    - ) -} - +
  • +
  • + +
  • +
  • + +
  • + + + + + + + + ); +}; diff --git a/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.module.css b/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.module.css new file mode 100644 index 000000000..16e538939 --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.module.css @@ -0,0 +1,13 @@ +.title { + text-align: center; + margin-top: 2rem; + color: #000091; +} + +.label-field { + min-width: 160px; + display: inline-block; +} +.field_container { + margin-bottom: 18px; +} diff --git a/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.tsx b/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.tsx new file mode 100644 index 000000000..a51dd3c6c --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.tsx @@ -0,0 +1,161 @@ +import "@gouvfr/dsfr/dist/component/table/table.min.css"; +import "@gouvfr/dsfr/dist/component/pagination/pagination.min.css"; +import "@gouvfr/dsfr/dist/component/select/select.min.css"; + +import { useRouter } from "next-router-mock"; + +import { formatDateAndHours } from "../../../utils/dateUtils"; +import { useDependencies } from "../../commun/contexts/useDependencies"; +import styles from "./EditUser.module.css"; + +type UsersListPageProps = Readonly<{ + users: any[]; +}>; + +export const EditUser = ({ user }: UsersListPageProps) => { + console.log("user ---------data---------", user); + const { wording } = useDependencies(); + const router = useRouter(); + const { paths } = useDependencies(); + + const Roles = ["Admin National", "Admin Regional", "Utilisateur"]; + const Profiles = [ + { profil_label: "Utilisateur lambda", profil_code: "f998021c-9613-4978-be6a-2b4cd9e24ffb" }, + { profil_label: "Equipe projet", profil_code: "4bbf1e31-180a-4d29-9973-54459dc3087d" }, + ]; + + const Institutions = [ + { inst_code_geo: "84", inst_libelle: "ARS Auvergne-Rhône-Alpes", inst_code: "ARS_84" }, + { inst_code_geo: "27", inst_libelle: "ARS Bourgogne-Franche-Comté", inst_code: "ARS_27" }, + { inst_code_geo: "53", inst_libelle: "ARS Bretagne", inst_code: "ARS_53" }, + { inst_code_geo: "24", inst_libelle: "ARS Centre-Val de Loire", inst_code: "ARS_24" }, + { inst_code_geo: "94", inst_libelle: "ARS Corse", inst_code: "ARS_94" }, + { inst_code_geo: "44", inst_libelle: "ARS Grand Est", inst_code: "ARS_44" }, + { inst_code_geo: "1", inst_libelle: "ARS Guadeloupe", inst_code: "ARS_01" }, + { inst_code_geo: "3", inst_libelle: "ARS Guyane", inst_code: "ARS_03" }, + { inst_code_geo: "32", inst_libelle: "ARS Hauts-de-France", inst_code: "ARS_32" }, + { inst_code_geo: "11", inst_libelle: "ARS Île-de-France", inst_code: "ARS_11" }, + { inst_code_geo: "4", inst_libelle: "ARS La Réunion", inst_code: "ARS_04" }, + { inst_code_geo: "2", inst_libelle: "ARS Martinique", inst_code: "ARS_02" }, + { inst_code_geo: "6", inst_libelle: "ARS Mayotte", inst_code: "ARS_06" }, + { inst_code_geo: "28", inst_libelle: "ARS Normandie", inst_code: "ARS_28" }, + { inst_code_geo: "75", inst_libelle: "ARS Nouvelle-Aquitaine", inst_code: "ARS_75" }, + { inst_code_geo: "76", inst_libelle: "ARS Occitanie", inst_code: "ARS_76" }, + { inst_code_geo: "52", inst_libelle: "ARS Pays de la Loire", inst_code: "ARS_52" }, + { inst_code_geo: "93", inst_libelle: "ARS Provence-Alpes-Côte d`Azur", inst_code: "ARS_93" }, + { inst_code_geo: "0", inst_libelle: "DNUM (SCN)", inst_code: "SCN" }, + { inst_code_geo: "75", inst_libelle: "CAT-AMANIA", inst_code: "CAT" }, + { inst_code_geo: "44", inst_libelle: "TEST", inst_code: "TEST" }, + ]; + + const saveButtonClick = () => { + /* updateProfile(userId, codeValue, { + institution: { + profilEJ: editableInstitutionEJValues, + profilMédicoSocial: editableInstitutionETMSValues, + profilETSanitaire: editableInstitutionETSANValues, + }, + autreRegion: { + profilEJ: editableAutreRegionEJValues, + profilMédicoSocial: editableAutreRegionETMSValues, + profilETSanitaire: editableAutreRegionETSANValues, + }, + });*/ + }; + + return ( +
    + {user && ( + <> +

    {wording.PAGE_EDIT_UTILISATEUR_TITRE}

    +
    +
    +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + + +
    + + )} +
    + ); +}; diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css new file mode 100644 index 000000000..06dbd6f67 --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css @@ -0,0 +1,69 @@ +.title { + text-align: center; + margin-top: 2rem; + color: #000091; +} + +.tab-title { + color: #000091; + font-weight: 900; + display: flex; + justify-content: center; +} + +.section-title { + font-weight: 900; +} + +.td-text { + word-wrap: break-word; +} + +.align table { + display: table; +} + +.align-text { + text-align: center; +} + +.pagination_container { + margin-top: 30px; + float: right; +} + +.filtres-big-container { +} +.filtres-container { +} +.search-bar-container { + float: right; +} +.search-bar { + width: 350px; +} + +.text_no_change { + text-transform: none; + font-weight: normal; + border: 1px solid #fff; + margin-bottom: 3px; +} + +.widthTD-small { + max-width: 20ch; + word-wrap: break-word; +} + +.btn-filtre { + margin: 0 !important; +} + +.collapseBox { + margin-top: 25px; + border: 1px solid #ddd; +} + +.filtre_details { + padding: 35px 150px; +} diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx new file mode 100644 index 000000000..7513ae1eb --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx @@ -0,0 +1,268 @@ +import "@gouvfr/dsfr/dist/component/table/table.min.css"; +import "@gouvfr/dsfr/dist/component/pagination/pagination.min.css"; +import "@gouvfr/dsfr/dist/component/select/select.min.css"; + +import { useRouter } from "next-router-mock"; + +import { formatDateAndHours } from "../../../utils/dateUtils"; +import { useDependencies } from "../../commun/contexts/useDependencies"; +import styles from "./UsersListPage.module.css"; + +type UsersListPageProps = Readonly<{ + users: any[]; +}>; + +export const UsersListPage = ({ users }: UsersListPageProps) => { + console.log("users ---------data---------", users); + const { wording } = useDependencies(); + const router = useRouter(); + const { paths } = useDependencies(); + + const Roles = ["Admin National", "Admin Regional", "Utilisateur"]; + const Profiles = [ + { profil_label: "Utilisateur lambda", profil_code: "f998021c-9613-4978-be6a-2b4cd9e24ffb" }, + { profil_label: "Equipe projet", profil_code: "4bbf1e31-180a-4d29-9973-54459dc3087d" }, + ]; + + const Institutions = [ + { inst_code_geo: "84", inst_libelle: "ARS Auvergne-Rhône-Alpes", inst_code: "ARS_84" }, + { inst_code_geo: "27", inst_libelle: "ARS Bourgogne-Franche-Comté", inst_code: "ARS_27" }, + { inst_code_geo: "53", inst_libelle: "ARS Bretagne", inst_code: "ARS_53" }, + { inst_code_geo: "24", inst_libelle: "ARS Centre-Val de Loire", inst_code: "ARS_24" }, + { inst_code_geo: "94", inst_libelle: "ARS Corse", inst_code: "ARS_94" }, + { inst_code_geo: "44", inst_libelle: "ARS Grand Est", inst_code: "ARS_44" }, + { inst_code_geo: "1", inst_libelle: "ARS Guadeloupe", inst_code: "ARS_01" }, + { inst_code_geo: "3", inst_libelle: "ARS Guyane", inst_code: "ARS_03" }, + { inst_code_geo: "32", inst_libelle: "ARS Hauts-de-France", inst_code: "ARS_32" }, + { inst_code_geo: "11", inst_libelle: "ARS Île-de-France", inst_code: "ARS_11" }, + { inst_code_geo: "4", inst_libelle: "ARS La Réunion", inst_code: "ARS_04" }, + { inst_code_geo: "2", inst_libelle: "ARS Martinique", inst_code: "ARS_02" }, + { inst_code_geo: "6", inst_libelle: "ARS Mayotte", inst_code: "ARS_06" }, + { inst_code_geo: "28", inst_libelle: "ARS Normandie", inst_code: "ARS_28" }, + { inst_code_geo: "75", inst_libelle: "ARS Nouvelle-Aquitaine", inst_code: "ARS_75" }, + { inst_code_geo: "76", inst_libelle: "ARS Occitanie", inst_code: "ARS_76" }, + { inst_code_geo: "52", inst_libelle: "ARS Pays de la Loire", inst_code: "ARS_52" }, + { inst_code_geo: "93", inst_libelle: "ARS Provence-Alpes-Côte d`Azur", inst_code: "ARS_93" }, + { inst_code_geo: "0", inst_libelle: "DNUM (SCN)", inst_code: "SCN" }, + { inst_code_geo: "75", inst_libelle: "CAT-AMANIA", inst_code: "CAT" }, + { inst_code_geo: "44", inst_libelle: "TEST", inst_code: "TEST" }, + ]; + + return ( +
    + {users.data && ( + <> +

    {wording.PAGE_UTILISATEUR_TITRE}

    +
    + {/* + */} +
    +
    +
    + +
    + +
    + +
    +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    +
    +
    +
    +
    + + {users.data.length === 0 ? ( +
    {wording.AUCUN_ELEMENT_TROUVE}
    + ) : ( +
    + + + + + + + + + + + + + + + {users.data.map((user: any) => { + const roleClass = user.roleId === "1" ? "error" : user.roleId === "2" ? "success" : "info"; + // console.log("user.profils", user.profils); + + return ( + + + + + + + + + + + + + ); + })} + +
    {wording.LASTNAME}{wording.FIRSTNAME} + {wording.EMAIL} + {wording.ROLE_}{wording.INSTITUTION}{wording.PROFILE}{wording.CREATION_DATE}
    + + {user.prenom} + + + + {user.nom} + + {user.email} + {Roles[user.roleId - 1]} + + {Institutions.filter((item) => item.inst_code_geo === user.institution2)[0]?.inst_libelle || "ARS Guyane"} + + {user.profils.map((profil: string) => { + const pr = Profiles.filter((item) => item.profil_code === profil); + return ( +
    + + {pr[0].profil_label} + +
    + ); + })} +
    {formatDateAndHours(user.dateCreation)}
    + +
    + )} + + )} +
    + ); +}; diff --git a/src/frontend/ui/parametrage-utilisateurs/usersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/usersListPage.tsx deleted file mode 100644 index 6a3e05900..000000000 --- a/src/frontend/ui/parametrage-utilisateurs/usersListPage.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import "@gouvfr/dsfr/dist/component/table/table.min.css"; - -export const UsersListPage = () => { - - return ( -
    - page users -
    - ); -}; \ No newline at end of file diff --git a/src/frontend/ui/profile/ProfilePage.tsx b/src/frontend/ui/profile/ProfilePage.tsx index 89a0b0384..381ac5f7a 100644 --- a/src/frontend/ui/profile/ProfilePage.tsx +++ b/src/frontend/ui/profile/ProfilePage.tsx @@ -4,79 +4,47 @@ import { useDependencies } from "../commun/contexts/useDependencies"; import styles from "./Profile.module.css"; export const ProfilePage = () => { - const { wording } = useDependencies(); - const { data } = useSession(); - - return ( -
    -
    -
    -

    {wording.USER_PROFILE}

    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - {wording.ROLE} - -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    + const { wording } = useDependencies(); + const { data } = useSession(); + return ( +
    +
    +
    +

    {wording.USER_PROFILE}

    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + {wording.ROLE} +
    + +
    - -
    - ); -} \ No newline at end of file +
    + + +
    +
    + + +
    + + +
    +
    + ); +}; diff --git a/src/pages/settings/profiles/index.tsx b/src/pages/settings/profiles/index.tsx index bb326c68d..586824ef7 100644 --- a/src/pages/settings/profiles/index.tsx +++ b/src/pages/settings/profiles/index.tsx @@ -1,4 +1,5 @@ import { GetStaticPropsResult } from "next"; +import { ProfilModel } from "../../../../database/models/ProfilModel"; import { getAllProfilesEndpoint } from "../../../backend/infrastructure/controllers/getAllProfilesEndpoint"; import { dependencies } from "../../../backend/infrastructure/dependencies"; @@ -6,7 +7,7 @@ import { useDependencies } from "../../../frontend/ui/commun/contexts/useDepende import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; import { ParametragePage } from "../../../frontend/ui/parametrage-profil/ParametragePage"; -type RouterProps = Readonly<{ profiles: any }>; +type RouterProps = Readonly<{ profiles: ProfilModel[] }>; export default function Router({ profiles }: RouterProps) { const { wording } = useDependencies(); @@ -23,16 +24,10 @@ export default function Router({ profiles }: RouterProps) { export async function getServerSideProps(): Promise> { try { - if (true) { - const profiles = await getAllProfilesEndpoint(dependencies); - return { - props: { profiles: JSON.parse(JSON.stringify(profiles)) }, - }; - } else { - return { - notFound: true, - }; - } + const profiles = await getAllProfilesEndpoint(dependencies); + return { + props: { profiles: JSON.parse(JSON.stringify(profiles)) }, + }; } catch (error) { throw error; } diff --git a/src/pages/settings/users/[userCode].tsx b/src/pages/settings/users/[userCode].tsx new file mode 100644 index 000000000..cb8931cd2 --- /dev/null +++ b/src/pages/settings/users/[userCode].tsx @@ -0,0 +1,60 @@ +import { GetStaticPathsResult, GetStaticPropsResult } from "next"; + +import { ProfileValue } from "../../../../database/models/ProfilModel"; +import { getUserByCodeEndpoint } from "../../../backend/infrastructure/controllers/getUserByCodeEndpoint"; +import { dependencies } from "../../../backend/infrastructure/dependencies"; +import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; +import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; +import { EditUser } from "../../../frontend/ui/parametrage-utilisateurs/EditUser/EditUser"; + +type RouterProps = Readonly<{ + user: any; +}>; + +export default function Router({ user }: RouterProps) { + const { wording } = useDependencies(); + useBreadcrumb([ + { + label: wording.USERS_LIST, + path: "/settings/users", + }, + { + label: wording.PAGE_EDIT_UTILISATEUR_TITRE, + path: "", + }, + ]); + // return ; + //return <>okkkkkkkkkkkkk user code est : {userCode}; + return ; +} + +export function getStaticPaths(): GetStaticPathsResult { + return { + fallback: "blocking", + paths: [], + }; +} + +export async function getStaticProps({ params }: { params: { userCode: string } }): Promise> { + try { + const { environmentVariables } = dependencies; + const user = await getUserByCodeEndpoint(dependencies, params.userCode); + + console.log("----user---", user); + if (!user) { + return { + notFound: true, + }; + } + + return { + props: { + user: JSON.parse(JSON.stringify(user)), + }, + + revalidate: Number(environmentVariables.TIME_OF_CACHE_PAGE), + }; + } catch (error) { + throw error; + } +} diff --git a/src/pages/settings/users/index.tsx b/src/pages/settings/users/index.tsx index e1de41602..568afcdc4 100644 --- a/src/pages/settings/users/index.tsx +++ b/src/pages/settings/users/index.tsx @@ -1,17 +1,33 @@ +import { GetStaticPropsResult } from "next"; +import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; -import { UsersListPage } from "../../../frontend/ui/parametrage-utilisateurs/usersListPage"; +import { UsersListPage } from "../../../frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage"; +import { getUsersListPaginatedEndpoint } from "../../../backend/infrastructure/controllers/getUsersListPaginatedEndpoint"; +import { dependencies } from "../../../backend/infrastructure/dependencies"; -const ParametrageUser = () => { - const { wording } = useDependencies(); +type RouterProps = Readonly<{ usersPaginatedList: any[] }>; - useBreadcrumb([ - { - label: wording.USERS_LIST, - path: "", - }, - ]); - return ; +export default function Router({ usersPaginatedList }: RouterProps) { + const { wording } = useDependencies(); + + useBreadcrumb([ + { + label: wording.USERS_LIST, + path: "", + }, + ]); + return ; } -export default ParametrageUser; \ No newline at end of file +export async function getServerSideProps(): Promise> { + try { + const users = await getUsersListPaginatedEndpoint(dependencies, "", "sortby", 1); + + return { + props: { usersPaginatedList: JSON.parse(JSON.stringify(users)) }, + }; + } catch (error) { + throw error; + } +} From a53483009d335fed0c8e88fcc80dd64e12283625 Mon Sep 17 00:00:00 2001 From: Adolato Date: Tue, 21 Nov 2023 13:20:28 +0100 Subject: [PATCH 06/67] (hel-537) hel-537/page-admin --- package.json | 3 +- .../TypeOrmUtilisateurLoader.ts | 9 +- src/frontend/ui/commun/Header/Header.tsx | 158 ++++---- .../KeyWordFilter/KeyWordFilter.module.css | 6 + .../KeyWordFilter/KeyWordFilter.tsx | 46 +++ .../PaginationBtn/PaginationBtn.module.css | 27 ++ .../PaginationBtn/PaginationBtn.tsx | 130 +++++++ .../UsersListPage/UsersListPage.module.css | 12 +- .../UsersListPage/UsersListPage.tsx | 353 ++++++++---------- src/pages/api/utilisateurs/getUsers.ts | 20 + src/pages/entite-juridique/[numeroFiness].tsx | 8 +- src/pages/settings/users/index.tsx | 30 +- yarn.lock | 209 ++++++++--- 13 files changed, 642 insertions(+), 369 deletions(-) create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.module.css create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.module.css create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx create mode 100644 src/pages/api/utilisateurs/getUsers.ts diff --git a/package.json b/package.json index 4728159e5..1e3a2d706 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "jsonwebtoken": "^9.0.0", "next": "13", "next-auth": "^4.22.1", + "next-usequerystate": "^1.12.2", "node-cache": "^5.1.2", "node-fetch": "2.6.7", "pg": "^8.7.3", @@ -149,4 +150,4 @@ "node": "16.16" }, "packageManager": "yarn@3.2.4" -} \ No newline at end of file +} diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index 912241b36..4e5f755ef 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -2,7 +2,7 @@ import { compare, genSalt, hash } from "bcrypt"; import { createHash } from "crypto"; import fs from "fs"; import path from "path"; -import { DataSource, Like } from "typeorm"; +import { DataSource, ILike } from "typeorm"; import { InstitutionModel } from "../../../../../database/models/InstitutionModel"; import { ProfilModel } from "../../../../../database/models/ProfilModel"; @@ -133,7 +133,7 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { if (key) { options = { ...options, - where: [{ nom: Like("%" + key.toString() + "%") }, { prenom: Like("%" + key.toString() + "%") }, { email: Like("%" + key.toString() + "%") }], + where: [{ nom: ILike("%" + key.toString() + "%") }, { prenom: ILike("%" + key.toString() + "%") }, { email: ILike("%" + key.toString() + "%") }], }; } /* @@ -159,8 +159,9 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { return { data, total, - pdescrtionA, - last_pdescrtion: Math.ceil(total / take), + keyWord: key, + currentPage: pdescrtionA, + lastPage: Math.ceil(total / take), }; } } diff --git a/src/frontend/ui/commun/Header/Header.tsx b/src/frontend/ui/commun/Header/Header.tsx index bb1d004f5..43ab99ec6 100644 --- a/src/frontend/ui/commun/Header/Header.tsx +++ b/src/frontend/ui/commun/Header/Header.tsx @@ -14,7 +14,6 @@ import { useDependencies } from "../contexts/useDependencies"; import { useOutsideClick } from "../hooks/useOutsideClick"; import styles from "./Header.module.css"; - export const Header = () => { const { paths, wording } = useDependencies(); const router = useRouter(); @@ -35,10 +34,9 @@ export const Header = () => { method: "POST", }).then(() => { signOut({ callbackUrl: paths.CONNEXION }); - setDisplayMenu(false) - }) - } - + setDisplayMenu(false); + }); + }; useEffect(() => { if (data?.user?.idUser) { @@ -61,18 +59,21 @@ export const Header = () => {
    - {router.pathname !== paths.ACCUEIL && router.pathname !== paths.CONNEXION && router.pathname !== paths.REINITIALISATION_PASSWORD && router.pathname !== paths.REGISTRATION && ( - - )} - {status !== "unauthenticated" && + {router.pathname !== paths.ACCUEIL && + router.pathname !== paths.CONNEXION && + router.pathname !== paths.REINITIALISATION_PASSWORD && + router.pathname !== paths.REGISTRATION && ( + + )} + {status !== "unauthenticated" && ( - } + )}
    @@ -94,49 +95,59 @@ export const Header = () => {
    - {router.pathname !== paths.ACCUEIL && router.pathname !== paths.FORGET_PASSWORD && router.pathname !== paths.CHANGE_PASSWORD && router.pathname !== paths.CONNEXION && router.pathname !== paths.SETTINGS && router.pathname !== paths.ADD_PROFILE && router.pathname !== paths.HISTORY && router.pathname !== paths.FAVORIS && router.pathname !== paths.REINITIALISATION_PASSWORD && router.pathname !== paths.REGISTRATION && ( - -
    - )} + )} {status === "authenticated" && paths.CONNEXION !== router.pathname ? (
    {displayMenu ? ( @@ -145,7 +156,8 @@ export const Header = () => { @@ -153,21 +165,21 @@ export const Header = () => { - {(data.user.role === '1' || data.user.role === '2') && ( + {(data.user.role === 1 || data.user.role === 2) && (
  • - +
    • @@ -175,35 +187,37 @@ export const Header = () => {
  • )} -
  • - -
  • + > + Profil +
  • +
  • + +
  • ) : null} -
    ) : null} @@ -218,9 +232,7 @@ export const Header = () => {
    • - +
    diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.module.css new file mode 100644 index 000000000..e06b23bfa --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.module.css @@ -0,0 +1,6 @@ +.search-bar-container { + float: right; +} +.search-bar { + width: 350px; +} diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx new file mode 100644 index 000000000..b9b8ac9a1 --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx @@ -0,0 +1,46 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-redundant-roles */ +/* eslint-disable jsx-a11y/anchor-is-valid */ + +import "@gouvfr/dsfr/dist/component/pagination/pagination.min.css"; + +import "@gouvfr/dsfr/dist/component/table/table.min.css"; +import "@gouvfr/dsfr/dist/component/select/select.min.css"; + +import styles from "./KeyWordFilter.module.css"; + +type KeyWordFilterProps = Readonly<{ + keyWord: string; + setKey: () => {}; + setUserData: () => {}; + setPage: () => {}; +}>; + +export const KeyWordFilter = ({ keyWord, setKey, setUserData, setPage }: KeyWordFilterProps) => { + async function handleChange(e: Event) { + e.preventDefault(); + setKey(e.target.value); + + const params = { key: e.target.value, sort: "", page: 1 }; + await fetch("/api/utilisateurs/getUsers?" + new URLSearchParams(params).toString(), { + headers: { "Content-Type": "application/json" }, + method: "GET", + }) + .then((response) => response.json()) + .then((users) => { + setUserData(users.data); + setPage(users.currentPage); + }); + } + return ( +
    + +
    + ); +}; diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.module.css new file mode 100644 index 000000000..bdf138e28 --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.module.css @@ -0,0 +1,27 @@ +.pagination_container { + margin-top: 30px; + float: right; +} + +.disabledBtn { + color: var(--text-disabled-grey); + cursor: not-allowed; +} + +.enabledBtn { + cursor: pointer !important; + --active-tint: var(--active) !important; + color: inherit !important; +} + +.enabledBtn:hover { + background-color: var(--hover); +} + +.currentPage { + --idle: transparent; + --hover: var(--background-active-blue-france-hover); + --active: var(--background-active-blue-france-active); + background-color: var(--background-active-blue-france); + color: var(--text-inverted-blue-france); +} diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx new file mode 100644 index 000000000..beff25f27 --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx @@ -0,0 +1,130 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-redundant-roles */ +/* eslint-disable jsx-a11y/anchor-is-valid */ + +import "@gouvfr/dsfr/dist/component/pagination/pagination.min.css"; + +import "@gouvfr/dsfr/dist/component/table/table.min.css"; +import "@gouvfr/dsfr/dist/component/select/select.min.css"; + +import styles from "./PaginationBtn.module.css"; + +type PaginationBtnProps = Readonly<{ + total: number; + lastPage: number; + setUserData: any; + setPage: any; + page: number; + keyWord: string; +}>; + +export const PaginationBtn = ({ setUserData, setPage, lastPage, page, keyWord }: PaginationBtnProps) => { + const intervalRecursive = (x: number, y: number, accum = []) => { + if (x + 1 === y) return accum; + return intervalRecursive(x + 1, y, accum.concat(x + 1)); + }; + + const changePage = async (e: MouseEvent, page: number) => { + e.preventDefault(); + + const params = { key: keyWord, sort: "", page: page }; + await fetch("/api/utilisateurs/getUsers?" + new URLSearchParams(params).toString(), { + headers: { "Content-Type": "application/json" }, + method: "GET", + }) + .then((response) => response.json()) + .then((users) => { + setUserData(users.data); + setPage(users.currentPage); + }); + }; + + return ( +
    + +
    + ); +}; diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css index 06dbd6f67..e1f8cc50e 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css @@ -27,21 +27,10 @@ text-align: center; } -.pagination_container { - margin-top: 30px; - float: right; -} - .filtres-big-container { } .filtres-container { } -.search-bar-container { - float: right; -} -.search-bar { - width: 350px; -} .text_no_change { text-transform: none; @@ -51,6 +40,7 @@ } .widthTD-small { + height: 90px; max-width: 20ch; word-wrap: break-word; } diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx index 7513ae1eb..854f4b879 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx @@ -1,22 +1,38 @@ +"use client"; + import "@gouvfr/dsfr/dist/component/table/table.min.css"; -import "@gouvfr/dsfr/dist/component/pagination/pagination.min.css"; + import "@gouvfr/dsfr/dist/component/select/select.min.css"; -import { useRouter } from "next-router-mock"; +import { useQueryState, parseAsInteger, parseAsString } from "next-usequerystate"; +import { useState } from "react"; +import { UtilisateurModel } from "../../../../../database/models/UtilisateurModel"; import { formatDateAndHours } from "../../../utils/dateUtils"; import { useDependencies } from "../../commun/contexts/useDependencies"; +import { PaginationBtn } from "./PaginationBtn/PaginationBtn"; import styles from "./UsersListPage.module.css"; +import { KeyWordFilter } from "./KeyWordFilter/KeyWordFilter"; type UsersListPageProps = Readonly<{ - users: any[]; + users: { + data: UtilisateurModel[]; + total: number; + currentPage: number; + keyWord: string; + lastPage: number; + }; + keyWord: string; }>; -export const UsersListPage = ({ users }: UsersListPageProps) => { - console.log("users ---------data---------", users); +export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { + const [userData, setUserData] = useState(users.data); + + const [key, setKey] = useQueryState("key", parseAsString.withDefault(keyWord)); + + const [page, setPage] = useQueryState("page", parseAsInteger.withDefault(users.currentPage)); + const { wording } = useDependencies(); - const router = useRouter(); - const { paths } = useDependencies(); const Roles = ["Admin National", "Admin Regional", "Utilisateur"]; const Profiles = [ @@ -50,214 +66,139 @@ export const UsersListPage = ({ users }: UsersListPageProps) => { return (
    - {users.data && ( + {userData && ( <>

    {wording.PAGE_UTILISATEUR_TITRE}


    - {/* - */} -
    -
    -
    - -
    - -
    - -
    -
    -
    -
    - - -
    -
    - - +
    +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    +
    - -
    - - -
    -
    +
    - - - - {users.data.length === 0 ? ( -
    {wording.AUCUN_ELEMENT_TROUVE}
    - ) : ( -
    - - - - - - - - - - - - - - - {users.data.map((user: any) => { - const roleClass = user.roleId === "1" ? "error" : user.roleId === "2" ? "success" : "info"; - // console.log("user.profils", user.profils); - - return ( - - - - - - - - - - - - ); - })} - -
    {wording.LASTNAME}{wording.FIRSTNAME} - {wording.EMAIL} - {wording.ROLE_}{wording.INSTITUTION}{wording.PROFILE}{wording.CREATION_DATE}
    - - {user.prenom} - - - - {user.nom} - - {user.email} - {Roles[user.roleId - 1]} - - {Institutions.filter((item) => item.inst_code_geo === user.institution2)[0]?.inst_libelle || "ARS Guyane"} - - {user.profils.map((profil: string) => { - const pr = Profiles.filter((item) => item.profil_code === profil); - return ( -
    - - {pr[0].profil_label} - -
    - ); - })} -
    {formatDateAndHours(user.dateCreation)}
    -
    - +
    + + + + + + + + + + + + + + + {userData.map((user: any) => { + const roleClass = user.roleId === "1" ? "error" : user.roleId === "2" ? "success" : "info"; + // console.log("user.profils", user.profils); + + return ( + + + + + + + + + + + + + ); + })} + +
    {wording.LASTNAME}{wording.FIRSTNAME} + {wording.EMAIL} + {wording.ROLE_}{wording.INSTITUTION}{wording.PROFILE}{wording.CREATION_DATE}
    + + {user.prenom} + + + + {user.nom} + + {user.email} + {Roles[user.roleId - 1]} + + {Institutions.filter((item) => item.inst_code_geo === user.institution2)[0]?.inst_libelle || "ARS Guyane"} + + {user.profils.map((profil: string) => { + const pr = Profiles.filter((item) => item.profil_code === profil); + return ( +
    + + {pr[0].profil_label} + +
    + ); + })} +
    {formatDateAndHours(user.dateCreation)}
    +
    )} diff --git a/src/pages/api/utilisateurs/getUsers.ts b/src/pages/api/utilisateurs/getUsers.ts new file mode 100644 index 000000000..7cdb8fdcf --- /dev/null +++ b/src/pages/api/utilisateurs/getUsers.ts @@ -0,0 +1,20 @@ +import { NextApiRequest, NextApiResponse } from "next"; + +import { getUsersListPaginatedEndpoint } from "../../../backend/infrastructure/controllers/getUsersListPaginatedEndpoint"; +import { dependencies } from "../../../backend/infrastructure/dependencies"; + +export default async function handler(request: NextApiRequest, response: NextApiResponse) { + try { + if (request.method !== "GET") { + response.status(405).send("Method not allowed"); + } + const key = request.query["key"] as string | ""; + const sort = request.query["sort"] as string | ""; + const page = request.query["page"] as number | 1; + const users = await getUsersListPaginatedEndpoint(dependencies, key, sort, page); + + return response.status(200).json(users); + } catch (error) { + return response.status(500); + } +} diff --git a/src/pages/entite-juridique/[numeroFiness].tsx b/src/pages/entite-juridique/[numeroFiness].tsx index 015f09623..9c16082d8 100644 --- a/src/pages/entite-juridique/[numeroFiness].tsx +++ b/src/pages/entite-juridique/[numeroFiness].tsx @@ -1,5 +1,5 @@ import { GetServerSidePropsContext, GetStaticPropsResult } from "next"; -import { getSession } from 'next-auth/react'; +import { getSession } from "next-auth/react"; import { rechercheParmiLesEntitésEtÉtablissementsEndpoint } from "../../backend/infrastructure/controllers/rechercheEndpoints"; import { récupèreLEntitéJuridiqueEndpoint } from "../../backend/infrastructure/controllers/récupèreLEntitéJuridiqueEndpoint"; @@ -14,7 +14,6 @@ import { EtablissementsTerritoriauxRattachésViewModel } from "../../frontend/ui import { PageEntitéJuridique } from "../../frontend/ui/entité-juridique/PageEntitéJuridique"; import { RechercheViewModel } from "../../frontend/ui/home/RechercheViewModel"; - type RouterProps = Readonly<{ entitéJuridique: EntitéJuridique; établissementsTerritoriauxRattachés: ÉtablissementTerritorialRattaché[]; @@ -24,7 +23,6 @@ type RouterProps = Readonly<{ export default function Router({ rechercheResult, entitéJuridique, établissementsTerritoriauxRattachés }: RouterProps) { const { wording, paths } = useDependencies(); - if (!établissementsTerritoriauxRattachés || !entitéJuridique) return null; const entitéJuridiqueViewModel = new EntitéJuridiqueViewModel(entitéJuridique, wording); @@ -42,7 +40,6 @@ export default function Router({ rechercheResult, entitéJuridique, établisseme ) : ( )} - ); } @@ -65,8 +62,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext): Pr rechercheResult: rechercheResult, }, }; - } - else { + } else { return { notFound: true, }; diff --git a/src/pages/settings/users/index.tsx b/src/pages/settings/users/index.tsx index 568afcdc4..c401da580 100644 --- a/src/pages/settings/users/index.tsx +++ b/src/pages/settings/users/index.tsx @@ -1,14 +1,23 @@ import { GetStaticPropsResult } from "next"; + import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; +import { getUsersListPaginatedEndpoint } from "../../../backend/infrastructure/controllers/getUsersListPaginatedEndpoint"; +import { dependencies } from "../../../backend/infrastructure/dependencies"; import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; import { UsersListPage } from "../../../frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage"; -import { getUsersListPaginatedEndpoint } from "../../../backend/infrastructure/controllers/getUsersListPaginatedEndpoint"; -import { dependencies } from "../../../backend/infrastructure/dependencies"; -type RouterProps = Readonly<{ usersPaginatedList: any[] }>; +interface IUsersPaginatedList { + data: UtilisateurModel[]; + total: number; + currentPage: number; + keyWord: string; + lastPage: number; +} + +type RouterProps = Readonly<{ usersPaginatedList: IUsersPaginatedList; keyWord: string }>; -export default function Router({ usersPaginatedList }: RouterProps) { +export default function Router({ usersPaginatedList, keyWord }: RouterProps) { const { wording } = useDependencies(); useBreadcrumb([ @@ -17,15 +26,20 @@ export default function Router({ usersPaginatedList }: RouterProps) { path: "", }, ]); - return ; + return ; } -export async function getServerSideProps(): Promise> { +export async function getServerSideProps(context): Promise> { try { - const users = await getUsersListPaginatedEndpoint(dependencies, "", "sortby", 1); + let { page, key } = context.query; + page = page as number | 1; + key = key as string | ""; + + const users = await getUsersListPaginatedEndpoint(dependencies, key, "Desc", page); + console.log("--users---", users); return { - props: { usersPaginatedList: JSON.parse(JSON.stringify(users)) }, + props: { usersPaginatedList: JSON.parse(JSON.stringify(users)), keyWord: key || "" }, }; } catch (error) { throw error; diff --git a/yarn.lock b/yarn.lock index 16b149c0e..aa410729d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -511,6 +511,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.21.0": + version: 7.23.4 + resolution: "@babel/runtime@npm:7.23.4" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 8eb6a6b2367f7d60e7f7dd83f477cc2e2fdb169e5460694d7614ce5c730e83324bcf29251b70940068e757ad1ee56ff8073a372260d90cad55f18a825caf97cd + languageName: node + linkType: hard + "@babel/template@npm:^7.18.10, @babel/template@npm:^7.3.3": version: 7.18.10 resolution: "@babel/template@npm:7.18.10" @@ -1457,10 +1466,10 @@ __metadata: languageName: node linkType: hard -"@sqltools/formatter@npm:^1.2.2": - version: 1.2.3 - resolution: "@sqltools/formatter@npm:1.2.3" - checksum: 5d80554b84ed15747fcfa6e488ef794c610c08152a53ebac0f270574ad938cdf39a02de7dfba4e9d9c33a790368f819945d315ee6dae360b220c29e092cba930 +"@sqltools/formatter@npm:^1.2.5": + version: 1.2.5 + resolution: "@sqltools/formatter@npm:1.2.5" + checksum: 9b8354e715467d660daa5afe044860b5686bbb1a5cb67a60866b932effafbf5e8b429f19a8ae67cd412065a4f067161f227e182f3664a0245339d5eb1e26e355 languageName: node linkType: hard @@ -2749,10 +2758,10 @@ __metadata: languageName: node linkType: hard -"app-root-path@npm:^3.0.0": - version: 3.0.0 - resolution: "app-root-path@npm:3.0.0" - checksum: ff91a24db2b55070f6b3e22e72ce8fe8ea847e19eb8a3cbb267f9e9ac2a8372db65114dd6798a4ed7897a6f475b90a49330b3e53bf199d47e6abb5c5279aa1d7 +"app-root-path@npm:^3.1.0": + version: 3.1.0 + resolution: "app-root-path@npm:3.1.0" + checksum: e3db3957aee197143a0f6c75e39fe89b19e7244f28b4f2944f7276a9c526d2a7ab2d115b4b2d70a51a65a9a3ca17506690e5b36f75a068a7e5a13f8c092389ba languageName: node linkType: hard @@ -3381,7 +3390,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.1.0": +"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -3608,6 +3617,17 @@ __metadata: languageName: node linkType: hard +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.1 + wrap-ansi: ^7.0.0 + checksum: 79648b3b0045f2e285b76fb2e24e207c6db44323581e421c3acbd0e86454cba1b37aea976ab50195a49e7384b871e6dfb2247ad7dec53c02454ac6497394cb56 + languageName: node + linkType: hard + "clone-regexp@npm:^2.1.0": version: 2.2.0 resolution: "clone-regexp@npm:2.2.0" @@ -4075,10 +4095,12 @@ __metadata: languageName: node linkType: hard -"date-fns@npm:^2.28.0": - version: 2.28.0 - resolution: "date-fns@npm:2.28.0" - checksum: a0516b2e4f99b8bffc6cc5193349f185f195398385bdcaf07f17c2c4a24473c99d933eb0018be4142a86a6d46cb0b06be6440ad874f15e795acbedd6fd727a1f +"date-fns@npm:^2.29.3": + version: 2.30.0 + resolution: "date-fns@npm:2.30.0" + dependencies: + "@babel/runtime": ^7.21.0 + checksum: f7be01523282e9bb06c0cd2693d34f245247a29098527d4420628966a2d9aad154bd0e90a6b1cf66d37adcb769cd108cf8a7bd49d76db0fb119af5cdd13644f4 languageName: node linkType: hard @@ -4439,10 +4461,10 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^16.0.0": - version: 16.0.1 - resolution: "dotenv@npm:16.0.1" - checksum: f459ffce07b977b7f15d8cc4ee69cdff77d4dd8c5dc8c85d2d485ee84655352c2415f9dd09d42b5b5985ced3be186130871b34e2f3e2569ebc72fbc2e8096792 +"dotenv@npm:^16.0.3": + version: 16.3.1 + resolution: "dotenv@npm:16.3.1" + checksum: 15d75e7279018f4bafd0ee9706593dd14455ddb71b3bcba9c52574460b7ccaf67d5cf8b2c08a5af1a9da6db36c956a04a1192b101ee102a3e0cf8817bbcf3dfd languageName: node linkType: hard @@ -5688,7 +5710,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.2.0": +"glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -5715,6 +5737,19 @@ __metadata: languageName: node linkType: hard +"glob@npm:^8.1.0": + version: 8.1.0 + resolution: "glob@npm:8.1.0" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^5.0.1 + once: ^1.3.0 + checksum: 92fbea3221a7d12075f26f0227abac435de868dd0736a17170663783296d0dd8d3d532a5672b4488a439bf5d7fb85cdd07c11185d6cd39184f0385cbdfb86a47 + languageName: node + linkType: hard + "global-dirs@npm:^0.1.0": version: 0.1.1 resolution: "global-dirs@npm:0.1.1" @@ -5971,6 +6006,7 @@ __metadata: next: 13 next-auth: ^4.22.1 next-router-mock: ^0.7.4 + next-usequerystate: ^1.12.2 node-cache: ^5.1.2 node-fetch: 2.6.7 pg: ^8.7.3 @@ -8249,6 +8285,13 @@ __metadata: languageName: node linkType: hard +"mitt@npm:^3.0.1": + version: 3.0.1 + resolution: "mitt@npm:3.0.1" + checksum: b55a489ac9c2949ab166b7f060601d3b6d893a852515ae9eca4e11df01c013876df777ea109317622b5c1c60e8aae252558e33c8c94e14124db38f64a39614b1 + languageName: node + linkType: hard + "mkdirp@npm:^0.5.3, mkdirp@npm:^0.5.5": version: 0.5.6 resolution: "mkdirp@npm:0.5.6" @@ -8269,6 +8312,15 @@ __metadata: languageName: node linkType: hard +"mkdirp@npm:^2.1.3": + version: 2.1.6 + resolution: "mkdirp@npm:2.1.6" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 8a1d09ffac585e55f41c54f445051f5bc33a7de99b952bb04c576cafdf1a67bb4bae8cb93736f7da6838771fbf75bc630430a3a59e1252047d2278690bd150ee + languageName: node + linkType: hard + "mrmime@npm:^1.0.0": version: 1.0.1 resolution: "mrmime@npm:1.0.1" @@ -8425,6 +8477,17 @@ __metadata: languageName: node linkType: hard +"next-usequerystate@npm:^1.12.2": + version: 1.12.2 + resolution: "next-usequerystate@npm:1.12.2" + dependencies: + mitt: ^3.0.1 + peerDependencies: + next: ">=13.4 <14.0.2 || ^14.0.3" + checksum: cfb79d26e373f51faffb9ef677b92d138ee4d7d9b155063a431987efec3b035dd799106423228dbdafe99f09878d32a27de8e4e280932f013f62787318c684f6 + languageName: node + linkType: hard + "next@npm:13": version: 13.2.4 resolution: "next@npm:13.2.4" @@ -9754,6 +9817,13 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.14.0": + version: 0.14.0 + resolution: "regenerator-runtime@npm:0.14.0" + checksum: 1c977ad82a82a4412e4f639d65d22be376d3ebdd30da2c003eeafdaaacd03fc00c2320f18120007ee700900979284fc78a9f00da7fb593f6e6eeebc673fba9a3 + languageName: node + linkType: hard + "regexp.prototype.flags@npm:^1.4.1, regexp.prototype.flags@npm:^1.4.3": version: 1.5.0 resolution: "regexp.prototype.flags@npm:1.5.0" @@ -10073,7 +10143,7 @@ __metadata: languageName: node linkType: hard -"sax@npm:>=0.6.0, sax@npm:^1.2.4": +"sax@npm:^1.2.4": version: 1.2.4 resolution: "sax@npm:1.2.4" checksum: d3df7d32b897a2c2f28e941f732c71ba90e27c24f62ee918bd4d9a8cfb3553f2f81e5493c7f0be94a11c1911b643a9108f231dd6f60df3fa9586b5d2e3e9e1fe @@ -11209,13 +11279,20 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:~2.4.0": +"tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:~2.4.0": version: 2.4.0 resolution: "tslib@npm:2.4.0" checksum: 8c4aa6a3c5a754bf76aefc38026134180c053b7bd2f81338cb5e5ebf96fefa0f417bff221592bf801077f5bf990562f6264fecbc42cd3309b33872cb6fc3b113 languageName: node linkType: hard +"tslib@npm:^2.5.0": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad + languageName: node + linkType: hard + "tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0" @@ -11371,42 +11448,40 @@ __metadata: linkType: hard "typeorm@npm:^0.3.6": - version: 0.3.6 - resolution: "typeorm@npm:0.3.6" + version: 0.3.17 + resolution: "typeorm@npm:0.3.17" dependencies: - "@sqltools/formatter": ^1.2.2 - app-root-path: ^3.0.0 + "@sqltools/formatter": ^1.2.5 + app-root-path: ^3.1.0 buffer: ^6.0.3 - chalk: ^4.1.0 + chalk: ^4.1.2 cli-highlight: ^2.1.11 - date-fns: ^2.28.0 - debug: ^4.3.3 - dotenv: ^16.0.0 - glob: ^7.2.0 - js-yaml: ^4.1.0 - mkdirp: ^1.0.4 + date-fns: ^2.29.3 + debug: ^4.3.4 + dotenv: ^16.0.3 + glob: ^8.1.0 + mkdirp: ^2.1.3 reflect-metadata: ^0.1.13 sha.js: ^2.4.11 - tslib: ^2.3.1 - uuid: ^8.3.2 - xml2js: ^0.4.23 - yargs: ^17.3.1 + tslib: ^2.5.0 + uuid: ^9.0.0 + yargs: ^17.6.2 peerDependencies: "@google-cloud/spanner": ^5.18.0 - "@sap/hana-client": ^2.11.14 - better-sqlite3: ^7.1.2 + "@sap/hana-client": ^2.12.25 + better-sqlite3: ^7.1.2 || ^8.0.0 hdb-pool: ^0.1.6 - ioredis: ^4.28.3 - mongodb: ^3.6.0 - mssql: ^6.3.1 - mysql2: ^2.2.5 + ioredis: ^5.0.4 + mongodb: ^5.2.0 + mssql: ^9.1.1 + mysql2: ^2.2.5 || ^3.0.1 oracledb: ^5.1.0 pg: ^8.5.1 pg-native: ^3.0.0 pg-query-stream: ^4.0.0 redis: ^3.1.1 || ^4.0.0 sql.js: ^1.4.0 - sqlite3: ^5.0.2 + sqlite3: ^5.0.3 ts-node: ^10.7.0 typeorm-aurora-data-api-driver: ^2.0.0 peerDependenciesMeta: @@ -11448,7 +11523,7 @@ __metadata: typeorm: cli.js typeorm-ts-node-commonjs: cli-ts-node-commonjs.js typeorm-ts-node-esm: cli-ts-node-esm.js - checksum: 7353b87a8161146c9bab765824857683f4755614c866326b1b260fdddc63470c7679e45c544f4761b7352d26b9f86bc933e1b44b0b1de4512cdc0ca5677db39a + checksum: 71fcb2b2e889c759b24add6c6ab7938c9a52f7c206b055f3a2abd77725acfec125b8f303e263381258ee03e52f7d3eb88c1fb893b15750b5237c8fc9db31ed78 languageName: node linkType: hard @@ -11616,6 +11691,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^9.0.0": + version: 9.0.1 + resolution: "uuid@npm:9.0.1" + bin: + uuid: dist/bin/uuid + checksum: 39931f6da74e307f51c0fb463dc2462807531dc80760a9bff1e35af4316131b4fc3203d16da60ae33f07fdca5b56f3f1dd662da0c99fea9aaeab2004780cc5f4 + languageName: node + linkType: hard + "v8-compile-cache-lib@npm:^3.0.1": version: 3.0.1 resolution: "v8-compile-cache-lib@npm:3.0.1" @@ -12022,23 +12106,6 @@ __metadata: languageName: node linkType: hard -"xml2js@npm:^0.4.23": - version: 0.4.23 - resolution: "xml2js@npm:0.4.23" - dependencies: - sax: ">=0.6.0" - xmlbuilder: ~11.0.0 - checksum: ca0cf2dfbf6deeaae878a891c8fbc0db6fd04398087084edf143cdc83d0509ad0fe199b890f62f39c4415cf60268a27a6aed0d343f0658f8779bd7add690fa98 - languageName: node - linkType: hard - -"xmlbuilder@npm:~11.0.0": - version: 11.0.1 - resolution: "xmlbuilder@npm:11.0.1" - checksum: 7152695e16f1a9976658215abab27e55d08b1b97bca901d58b048d2b6e106b5af31efccbdecf9b07af37c8377d8e7e821b494af10b3a68b0ff4ae60331b415b0 - languageName: node - linkType: hard - "xmlchars@npm:^2.2.0": version: 2.2.0 resolution: "xmlchars@npm:2.2.0" @@ -12122,6 +12189,13 @@ __metadata: languageName: node linkType: hard +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c + languageName: node + linkType: hard + "yargs@npm:^15.4.1": version: 15.4.1 resolution: "yargs@npm:15.4.1" @@ -12171,6 +12245,21 @@ __metadata: languageName: node linkType: hard +"yargs@npm:^17.6.2": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: ^8.0.1 + escalade: ^3.1.1 + get-caller-file: ^2.0.5 + require-directory: ^2.1.1 + string-width: ^4.2.3 + y18n: ^5.0.5 + yargs-parser: ^21.1.1 + checksum: 73b572e863aa4a8cbef323dd911d79d193b772defd5a51aab0aca2d446655216f5002c42c5306033968193bdbf892a7a4c110b0d77954a7fdf563e653967b56a + languageName: node + linkType: hard + "yn@npm:3.1.1": version: 3.1.1 resolution: "yn@npm:3.1.1" From 439d1e51d8a3a24d06771ede50f5f3bbb36add72 Mon Sep 17 00:00:00 2001 From: Adolato Date: Tue, 21 Nov 2023 15:16:49 +0100 Subject: [PATCH 07/67] (hel-537) hel-537/page-admin --- .../TypeOrmUtilisateurLoader.ts | 21 ++- .../PaginationBtn/PaginationBtn.tsx | 156 +++++++++--------- .../UsersListPage/UsersListPage.tsx | 120 +++++++------- 3 files changed, 154 insertions(+), 143 deletions(-) diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index 4e5f755ef..60b4c182a 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -123,9 +123,13 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { return profiles; } - async getUsersListPaginated(key: string, sort: string, pdescrtion: number): Promise { + async getUsersListPaginated(key: string, sort: string, currentPage: number): Promise { // return await (await this.orm).getRepository(UtilisateurModel).find(); + if (key === undefined) { + key = ""; + } + const utilisateurRepo = (await this.orm).getRepository(UtilisateurModel); let options = {}; @@ -146,21 +150,26 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { }; }*/ - const pdescrtionA: number = parseInt(pdescrtion as any) || 1; - const take = 5; - const total = await utilisateurRepo.count(); + const currentPageA: number = parseInt(currentPage as any) || 1; + const take = 10; + + const total = await utilisateurRepo.countBy([ + { nom: ILike("%" + key.toString() + "%") }, + { prenom: ILike("%" + key.toString() + "%") }, + { email: ILike("%" + key.toString() + "%") }, + ]); const data = await utilisateurRepo.find({ ...options, take, - skip: (pdescrtionA - 1) * take, + skip: (currentPageA - 1) * take, }); return { data, total, keyWord: key, - currentPage: pdescrtionA, + currentPage: currentPageA, lastPage: Math.ceil(total / take), }; } diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx index beff25f27..1180d75d0 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx @@ -42,89 +42,91 @@ export const PaginationBtn = ({ setUserData, setPage, lastPage, page, keyWord }: return (
    - + )}
    ); }; diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx index 854f4b879..1aeeb770c 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx @@ -70,69 +70,70 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { <>

    {wording.PAGE_UTILISATEUR_TITRE}


    - {userData.length === 0 ? ( -
    {wording.AUCUN_ELEMENT_TROUVE}
    - ) : ( -
    -
    -
    - - -
    -
    -
    -
    -
    - - -
    - -
    - - -
    - -
    - - -
    -
    +
    +
    + + +
    + +
    +
    +
    +
    + + +
    + +
    + + +
    + +
    + +
    -
    +
    +
    +
    + {userData.length === 0 ? ( +
    {wording.AUCUN_ELEMENT_TROUVE}
    + ) : ( +
    @@ -152,7 +153,6 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { {userData.map((user: any) => { const roleClass = user.roleId === "1" ? "error" : user.roleId === "2" ? "success" : "info"; - // console.log("user.profils", user.profils); return ( From b2a530a4fcc4044c9c51a9e747fb6cb6f44b7145 Mon Sep 17 00:00:00 2001 From: Adolato Date: Tue, 21 Nov 2023 16:29:11 +0100 Subject: [PATCH 08/67] (hel-537) hel-537/page-admin --- .../utilisateur-loader/TypeOrmUtilisateurLoader.ts | 6 +----- .../UsersListPage/KeyWordFilter/KeyWordFilter.tsx | 4 +++- .../UsersListPage/PaginationBtn/PaginationBtn.tsx | 8 +++++--- .../UsersListPage/UsersListPage.tsx | 14 ++++++++++++-- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index 60b4c182a..ad36cd69e 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -123,13 +123,9 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { return profiles; } - async getUsersListPaginated(key: string, sort: string, currentPage: number): Promise { + async getUsersListPaginated(key = "", sort: string, currentPage: number): Promise { // return await (await this.orm).getRepository(UtilisateurModel).find(); - if (key === undefined) { - key = ""; - } - const utilisateurRepo = (await this.orm).getRepository(UtilisateurModel); let options = {}; diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx index b9b8ac9a1..f6315a10e 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx @@ -15,9 +15,10 @@ type KeyWordFilterProps = Readonly<{ setKey: () => {}; setUserData: () => {}; setPage: () => {}; + setLastPage: () => {}; }>; -export const KeyWordFilter = ({ keyWord, setKey, setUserData, setPage }: KeyWordFilterProps) => { +export const KeyWordFilter = ({ keyWord, setKey, setUserData, setPage, setLastPage }: KeyWordFilterProps) => { async function handleChange(e: Event) { e.preventDefault(); setKey(e.target.value); @@ -31,6 +32,7 @@ export const KeyWordFilter = ({ keyWord, setKey, setUserData, setPage }: KeyWord .then((users) => { setUserData(users.data); setPage(users.currentPage); + setLastPage(users.lastPage); }); } return ( diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx index 1180d75d0..1356156fd 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx @@ -13,13 +13,14 @@ import styles from "./PaginationBtn.module.css"; type PaginationBtnProps = Readonly<{ total: number; lastPage: number; - setUserData: any; - setPage: any; + setUserData: () => {}; + setPage: () => {}; + setLastPage: () => {}; page: number; keyWord: string; }>; -export const PaginationBtn = ({ setUserData, setPage, lastPage, page, keyWord }: PaginationBtnProps) => { +export const PaginationBtn = ({ setUserData, setPage, lastPage, page, keyWord, setLastPage }: PaginationBtnProps) => { const intervalRecursive = (x: number, y: number, accum = []) => { if (x + 1 === y) return accum; return intervalRecursive(x + 1, y, accum.concat(x + 1)); @@ -37,6 +38,7 @@ export const PaginationBtn = ({ setUserData, setPage, lastPage, page, keyWord }: .then((users) => { setUserData(users.data); setPage(users.currentPage); + setLastPage(users.lastPage); }); }; diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx index 1aeeb770c..8c15c9279 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx @@ -28,6 +28,8 @@ type UsersListPageProps = Readonly<{ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { const [userData, setUserData] = useState(users.data); + const [lastPage, setLastPage] = useState(users.lastPage); + const [key, setKey] = useQueryState("key", parseAsString.withDefault(keyWord)); const [page, setPage] = useQueryState("page", parseAsInteger.withDefault(users.currentPage)); @@ -73,7 +75,7 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => {
    - + @@ -198,7 +200,15 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { })}
    - +
    )} From e78d0a164354500511163d91ea852314247bc823 Mon Sep 17 00:00:00 2001 From: Adolato Date: Tue, 21 Nov 2023 17:41:32 +0100 Subject: [PATCH 09/67] (hel-537) hel-537/page-admin --- database/models/UtilisateurModel.ts | 3 --- .../TypeOrmUtilisateurLoader.ts | 18 ++++++++++++------ .../UsersListPage/UsersListPage.tsx | 9 +++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/database/models/UtilisateurModel.ts b/database/models/UtilisateurModel.ts index f7deeeeab..6f4fc5e7d 100644 --- a/database/models/UtilisateurModel.ts +++ b/database/models/UtilisateurModel.ts @@ -30,9 +30,6 @@ export class UtilisateurModel { @JoinColumn({ name: "ut_institution", referencedColumnName: "id" }) public institution!: InstitutionModel; - @Column({ name: "ut_institution" }) - public institution2!: number; - @Column({ name: "ut_actif", default: false }) public actif!: boolean; diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index ad36cd69e..0e68f2428 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -130,10 +130,16 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { let options = {}; + const conditions = [ + { nom: ILike("%" + key.toString() + "%") }, + { prenom: ILike("%" + key.toString() + "%") }, + { email: ILike("%" + key.toString() + "%") }, + ]; + if (key) { options = { ...options, - where: [{ nom: ILike("%" + key.toString() + "%") }, { prenom: ILike("%" + key.toString() + "%") }, { email: ILike("%" + key.toString() + "%") }], + where: conditions, }; } /* @@ -149,16 +155,16 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { const currentPageA: number = parseInt(currentPage as any) || 1; const take = 10; - const total = await utilisateurRepo.countBy([ - { nom: ILike("%" + key.toString() + "%") }, - { prenom: ILike("%" + key.toString() + "%") }, - { email: ILike("%" + key.toString() + "%") }, - ]); + const total = await utilisateurRepo.countBy(conditions); const data = await utilisateurRepo.find({ ...options, take, skip: (currentPageA - 1) * take, + relations: { + role: true, + institution: true, + }, }); return { diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx index 8c15c9279..efd465332 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx @@ -36,7 +36,6 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { const { wording } = useDependencies(); - const Roles = ["Admin National", "Admin Regional", "Utilisateur"]; const Profiles = [ { profil_label: "Utilisateur lambda", profil_code: "f998021c-9613-4978-be6a-2b4cd9e24ffb" }, { profil_label: "Equipe projet", profil_code: "4bbf1e31-180a-4d29-9973-54459dc3087d" }, @@ -154,7 +153,7 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { {userData.map((user: any) => { - const roleClass = user.roleId === "1" ? "error" : user.roleId === "2" ? "success" : "info"; + const roleClass = user.role.id === 1 ? "error" : user.role.id === 2 ? "success" : "info"; return ( @@ -171,12 +170,10 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { {user.email} - {Roles[user.roleId - 1]} + {user.role.libelle} - - {Institutions.filter((item) => item.inst_code_geo === user.institution2)[0]?.inst_libelle || "ARS Guyane"} - + {user.institution.libelle} {user.profils.map((profil: string) => { From db0b7e60a860e6ddbe42e923fac12c2cae480cb9 Mon Sep 17 00:00:00 2001 From: Adolato Date: Wed, 22 Nov 2023 22:00:56 +0100 Subject: [PATCH 10/67] (hel-537) hel-537/page-admin --- database/models/UtilisateurModel.ts | 3 + .../controllers/getAllRolesEndpoint.ts | 13 ++ .../getUsersListPaginatedEndpoint.ts | 12 +- src/backend/infrastructure/dependencies.ts | 7 +- .../gateways/role-loader/TypeOrmRoleLoader.ts | 12 ++ .../TypeOrmUtilisateurLoader.ts | 55 ++++---- .../m\303\251tier/gateways/RoleLoader.ts" | 5 + .../gateways/UtilisateurLoader.ts" | 2 +- .../m\303\251tier/use-cases/RolesUseCase.ts" | 10 ++ .../use-cases/UtilisateursUseCase.ts" | 4 +- .../EditUser/EditUser.tsx | 78 +++++------ .../AdvancedFilter/AdvancedFilter.module.css | 3 + .../Filter/AdvancedFilter/AdvancedFilter.tsx | 120 ++++++++++++++++ .../KeyWordFilter/KeyWordFilter.module.css | 0 .../KeyWordFilter/KeyWordFilter.tsx | 3 - .../UsersListPage/UsersListPage.module.css | 4 - .../UsersListPage/UsersListPage.tsx | 129 ++++++------------ src/pages/api/utilisateurs/getUsers.ts | 10 +- src/pages/settings/users/index.tsx | 61 ++++++++- 19 files changed, 358 insertions(+), 173 deletions(-) create mode 100644 src/backend/infrastructure/controllers/getAllRolesEndpoint.ts create mode 100644 src/backend/infrastructure/gateways/role-loader/TypeOrmRoleLoader.ts create mode 100644 "src/backend/m\303\251tier/gateways/RoleLoader.ts" create mode 100644 "src/backend/m\303\251tier/use-cases/RolesUseCase.ts" create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.module.css create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx rename src/frontend/ui/parametrage-utilisateurs/UsersListPage/{ => Filter}/KeyWordFilter/KeyWordFilter.module.css (100%) rename src/frontend/ui/parametrage-utilisateurs/UsersListPage/{ => Filter}/KeyWordFilter/KeyWordFilter.tsx (92%) diff --git a/database/models/UtilisateurModel.ts b/database/models/UtilisateurModel.ts index 6f4fc5e7d..d9469b39e 100644 --- a/database/models/UtilisateurModel.ts +++ b/database/models/UtilisateurModel.ts @@ -30,6 +30,9 @@ export class UtilisateurModel { @JoinColumn({ name: "ut_institution", referencedColumnName: "id" }) public institution!: InstitutionModel; + @Column({ name: "ut_institution" }) + public institutionId!: number; + @Column({ name: "ut_actif", default: false }) public actif!: boolean; diff --git a/src/backend/infrastructure/controllers/getAllRolesEndpoint.ts b/src/backend/infrastructure/controllers/getAllRolesEndpoint.ts new file mode 100644 index 000000000..d0a392f96 --- /dev/null +++ b/src/backend/infrastructure/controllers/getAllRolesEndpoint.ts @@ -0,0 +1,13 @@ +import { RoleModel } from "../../../../database/models/RoleModel"; +import { RolesUseCase } from "../../métier/use-cases/RolesUseCase"; +import { Dependencies } from "../dependencies"; + +export async function getAllRolesEndpoint(dependencies: Dependencies): Promise { + try { + const RoleUseCase = new RolesUseCase(dependencies.roleLoader); + return await RoleUseCase.getAllRoles(); + } catch (error) { + dependencies.logger.error(error); + throw error; + } +} diff --git a/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts b/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts index 295f56b84..264a9b08f 100644 --- a/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts +++ b/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts @@ -2,10 +2,18 @@ import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; import { UtilisateursUseCase } from "../../métier/use-cases/UtilisateursUseCase"; import { Dependencies } from "../dependencies"; -export async function getUsersListPaginatedEndpoint(dependencies: Dependencies, key: string, sort: string, pdescrtion: number): Promise { +export async function getUsersListPaginatedEndpoint( + dependencies: Dependencies, + key: string, + sort: string, + pdescrtion: number, + institutionId: number, + roleId: number, + profilId: string +): Promise { try { const UtilisateurUseCase = new UtilisateursUseCase(dependencies.utilisateurLoader); - return await UtilisateurUseCase.getUsersListPaginated(key, sort, pdescrtion); + return await UtilisateurUseCase.getUsersListPaginated(key, sort, pdescrtion, institutionId, roleId, profilId); } catch (error) { dependencies.logger.error(error); throw error; diff --git a/src/backend/infrastructure/dependencies.ts b/src/backend/infrastructure/dependencies.ts index 297bd5034..87731beac 100644 --- a/src/backend/infrastructure/dependencies.ts +++ b/src/backend/infrastructure/dependencies.ts @@ -20,6 +20,7 @@ import { TypeOrmForgetPasswordLoader } from "./gateways/forget-password-loader/T import { ConsoleLogger } from "./gateways/logger/ConsoleLogger"; import { typeOrmOrm } from "./gateways/orm/typeOrmOrm"; import { TypeOrmProfileLoader } from "./gateways/profile-loader/TypeOrmProfileLoader"; +import { TypeOrmRoleLoader } from "./gateways/role-loader/TypeOrmRoleLoader"; import { TypeOrmRechercheLoader } from "./gateways/recherche-loader/TypeOrmRechercheLoader"; import { TypeOrmSearchHistoryLoader } from "./gateways/search-history-loader/TypeOrmSearchHistoryLoader"; import { TypeOrmUtilisateurLoader } from "./gateways/utilisateur-loader/TypeOrmUtilisateurLoader"; @@ -40,7 +41,8 @@ export type Dependencies = Readonly<{ changePasswordLoader: ChangePasswordLoader; forgetPasswordLoader: TypeOrmForgetPasswordLoader; searchHistoryLoader: SearchHistoryLoader; - profileLoader: TypeOrmProfileLoader + profileLoader: TypeOrmProfileLoader; + roleLoader: TypeOrmRoleLoader; }>; const createDependencies = (): Dependencies => { @@ -68,7 +70,8 @@ const createDependencies = (): Dependencies => { changePasswordLoader: new TypeOrmChangePasswordLoader(orm), forgetPasswordLoader: new TypeOrmForgetPasswordLoader(orm), searchHistoryLoader: new TypeOrmSearchHistoryLoader(orm), - profileLoader: new TypeOrmProfileLoader(orm) + profileLoader: new TypeOrmProfileLoader(orm), + roleLoader: new TypeOrmRoleLoader(orm), }; }; diff --git a/src/backend/infrastructure/gateways/role-loader/TypeOrmRoleLoader.ts b/src/backend/infrastructure/gateways/role-loader/TypeOrmRoleLoader.ts new file mode 100644 index 000000000..c22dfdbc8 --- /dev/null +++ b/src/backend/infrastructure/gateways/role-loader/TypeOrmRoleLoader.ts @@ -0,0 +1,12 @@ +import { DataSource } from "typeorm"; + +import { RoleModel } from "../../../../../database/models/RoleModel"; +import { RoleLoader } from "../../../métier/gateways/RoleLoader"; + +export class TypeOrmRoleLoader implements RoleLoader { + constructor(private readonly orm: Promise) {} + + async getAllRoles(): Promise { + return await (await this.orm).getRepository(RoleModel).find(); + } +} diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index 0e68f2428..ae6e8793c 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -2,7 +2,7 @@ import { compare, genSalt, hash } from "bcrypt"; import { createHash } from "crypto"; import fs from "fs"; import path from "path"; -import { DataSource, ILike } from "typeorm"; +import { DataSource, ILike, Like } from "typeorm"; import { InstitutionModel } from "../../../../../database/models/InstitutionModel"; import { ProfilModel } from "../../../../../database/models/ProfilModel"; @@ -123,42 +123,49 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { return profiles; } - async getUsersListPaginated(key = "", sort: string, currentPage: number): Promise { + async getUsersListPaginated(key = "", sort: string, currentPage: number, institutionId: number, roleId: number, profilId: string): Promise { // return await (await this.orm).getRepository(UtilisateurModel).find(); const utilisateurRepo = (await this.orm).getRepository(UtilisateurModel); + /* + const institutionCondition = { institution: { id: 19 } }; + const roleCondition = { role: { id: 3 } }; + const profilCondition = { profils: ["4bbf1e31-180a-4d29-9973-54459dc3087d"] };*/ - let options = {}; + let institutionCondition = {}; + if (institutionId) { + institutionCondition = { institution: { id: institutionId } }; + } - const conditions = [ - { nom: ILike("%" + key.toString() + "%") }, - { prenom: ILike("%" + key.toString() + "%") }, - { email: ILike("%" + key.toString() + "%") }, - ]; + let roleCondition = {}; + if (profilId) { + roleCondition = { role: { id: roleId } }; + } - if (key) { - options = { - ...options, - where: conditions, - }; + let profilCondition = {}; + if (profilId) { + profilCondition = { profils: [profilId] }; } - /* - if (sort) { - options = { - ...options, - order: { - libelle: sort.toString().toUpperCase(), - }, - }; - }*/ + + const selectConditions = { ...institutionCondition, ...roleCondition, ...profilCondition }; + + const conditions = [ + { nom: ILike("%" + key.toString() + "%"), ...selectConditions }, + { prenom: ILike("%" + key.toString() + "%"), ...selectConditions }, + { email: ILike("%" + key.toString() + "%"), ...selectConditions }, + ]; const currentPageA: number = parseInt(currentPage as any) || 1; - const take = 10; + const take = 5; + + console.log("99999999999999999999-----"); + + console.log(conditions); const total = await utilisateurRepo.countBy(conditions); const data = await utilisateurRepo.find({ - ...options, + where: conditions, take, skip: (currentPageA - 1) * take, relations: { diff --git "a/src/backend/m\303\251tier/gateways/RoleLoader.ts" "b/src/backend/m\303\251tier/gateways/RoleLoader.ts" new file mode 100644 index 000000000..18f80f3e2 --- /dev/null +++ "b/src/backend/m\303\251tier/gateways/RoleLoader.ts" @@ -0,0 +1,5 @@ +import { RoleModel } from "../../../../database/models/RoleModel"; + +export interface RoleLoader { + getAllRoles(): Promise; +} diff --git "a/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" "b/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" index f1b2fe44c..34d9afc94 100644 --- "a/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" +++ "b/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" @@ -10,6 +10,6 @@ export interface UtilisateurLoader { createAccount(firstName: string, lastName: string, email: string, institution: string): Promise; getUserProfiles(codes: string[]): Promise; checkIfAdmin(userId: string): Promise; - getUsersListPaginated(key: string, sort: string, pdescrtion: number): Promise; + getUsersListPaginated(key: string, sort: string, pdescrtion: number, institutionId: number, roleId: number, profilId: string): Promise; getUserByCode(code: string): Promise; } diff --git "a/src/backend/m\303\251tier/use-cases/RolesUseCase.ts" "b/src/backend/m\303\251tier/use-cases/RolesUseCase.ts" new file mode 100644 index 000000000..f767752e4 --- /dev/null +++ "b/src/backend/m\303\251tier/use-cases/RolesUseCase.ts" @@ -0,0 +1,10 @@ +import { RoleModel } from "../../../../database/models/RoleModel"; +import { RoleLoader } from "../gateways/RoleLoader"; + +export class RolesUseCase { + constructor(private roleLoader: RoleLoader) {} + + async getAllRoles(): Promise { + return await this.roleLoader.getAllRoles(); + } +} diff --git "a/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" "b/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" index 43609ae51..1d82c9b6c 100644 --- "a/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" +++ "b/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" @@ -4,8 +4,8 @@ import { UtilisateurLoader } from "../gateways/UtilisateurLoader"; export class UtilisateursUseCase { constructor(private utilisateurLoader: UtilisateurLoader) {} - async getUsersListPaginated(key: string, sort: string, pdescrtion: number): Promise { - return await this.utilisateurLoader.getUsersListPaginated(key, sort, pdescrtion); + async getUsersListPaginated(key: string, sort: string, pdescrtion: number, institutionId: number, roleId: number, profilId: string): Promise { + return await this.utilisateurLoader.getUsersListPaginated(key, sort, pdescrtion, institutionId, roleId, profilId); } async getUserByCode(code: string): Promise { diff --git a/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.tsx b/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.tsx index a51dd3c6c..f5dc3c3d0 100644 --- a/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/EditUser/EditUser.tsx @@ -1,6 +1,7 @@ import "@gouvfr/dsfr/dist/component/table/table.min.css"; import "@gouvfr/dsfr/dist/component/pagination/pagination.min.css"; import "@gouvfr/dsfr/dist/component/select/select.min.css"; +import "@gouvfr/dsfr/dist/component/checkbox/checkbox.min.css"; import { useRouter } from "next-router-mock"; @@ -70,86 +71,85 @@ export const EditUser = ({ user }: UsersListPageProps) => {

    {wording.PAGE_EDIT_UTILISATEUR_TITRE}


    -
    - -
    -
    -
    -
    - -
    - -
    -
    -
    - - -
    -
    +
    + + Profils + +
    +
    + + +
    +
    +
    + +
    +
    + + +
    +
    +
    + +
    +
    + diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.module.css new file mode 100644 index 000000000..530077144 --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.module.css @@ -0,0 +1,3 @@ +.filtre_details { + padding: 35px 150px; +} diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx new file mode 100644 index 000000000..181bd7b24 --- /dev/null +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx @@ -0,0 +1,120 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-redundant-roles */ +/* eslint-disable jsx-a11y/anchor-is-valid */ + +import "@gouvfr/dsfr/dist/component/select/select.min.css"; +import { InstitutionModel } from "../../../../../../../database/models/InstitutionModel"; +import { ProfilModel } from "../../../../../../../database/models/ProfilModel"; +import { RoleModel } from "../../../../../../../database/models/RoleModel"; +import styles from "./AdvancedFilter.module.css"; + +type KeyWordFilterProps = Readonly<{ + keyWord: string; + setKey: () => {}; + setUserData: () => {}; + setPage: () => {}; + setLastPage: () => {}; + + institutions: InstitutionModel[]; + profiles: ProfilModel[]; + roles: RoleModel[]; + profileId: number; + roleId: number; + setRoleId: number; +}>; + +export const AdvancedFilter = ({ + keyWord, + setKey, + setUserData, + setPage, + setLastPage, + institutions, + profiles, + roles, + setInstitutionId, + institutionId, + setProfileId, + profileId, + roleId, + setRoleId, + key, + page, +}: KeyWordFilterProps) => { + async function handleChangeInstitution(e: React.ChangeEvent) { + e.preventDefault(); + + console.log("onChange TextInput value: " + e.target.value); + const keyValue = key ? key : ""; + console.log("key--------------: " + key); + setInstitutionId(e.target.value); + + const params = { key: keyValue, sort: "", page: page, institutionId: e.target.value }; + await fetch("/api/utilisateurs/getUsers?" + new URLSearchParams(params).toString(), { + headers: { "Content-Type": "application/json" }, + method: "GET", + }) + .then((response) => response.json()) + .then((users) => { + setUserData(users.data); + setPage(users.currentPage); + setLastPage(users.lastPage); + }); + } + + return ( +
    +
    + + + +
    +
    + + +
    + +
    + + +
    +
    + ); +}; diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.module.css similarity index 100% rename from src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.module.css rename to src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.module.css diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.tsx similarity index 92% rename from src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx rename to src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.tsx index f6315a10e..af9e2fdee 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/KeyWordFilter/KeyWordFilter.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.tsx @@ -3,9 +3,6 @@ /* eslint-disable jsx-a11y/no-redundant-roles */ /* eslint-disable jsx-a11y/anchor-is-valid */ -import "@gouvfr/dsfr/dist/component/pagination/pagination.min.css"; - -import "@gouvfr/dsfr/dist/component/table/table.min.css"; import "@gouvfr/dsfr/dist/component/select/select.min.css"; import styles from "./KeyWordFilter.module.css"; diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css index e1f8cc50e..cdb048def 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.module.css @@ -53,7 +53,3 @@ margin-top: 25px; border: 1px solid #ddd; } - -.filtre_details { - padding: 35px 150px; -} diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx index efd465332..1ef12674b 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx @@ -7,12 +7,16 @@ import "@gouvfr/dsfr/dist/component/select/select.min.css"; import { useQueryState, parseAsInteger, parseAsString } from "next-usequerystate"; import { useState } from "react"; +import { InstitutionModel } from "../../../../../database/models/InstitutionModel"; +import { ProfilModel } from "../../../../../database/models/ProfilModel"; +import { RoleModel } from "../../../../../database/models/RoleModel"; import { UtilisateurModel } from "../../../../../database/models/UtilisateurModel"; import { formatDateAndHours } from "../../../utils/dateUtils"; import { useDependencies } from "../../commun/contexts/useDependencies"; +import { AdvancedFilter } from "./Filter/AdvancedFilter/AdvancedFilter"; +import { KeyWordFilter } from "./Filter/KeyWordFilter/KeyWordFilter"; import { PaginationBtn } from "./PaginationBtn/PaginationBtn"; import styles from "./UsersListPage.module.css"; -import { KeyWordFilter } from "./KeyWordFilter/KeyWordFilter"; type UsersListPageProps = Readonly<{ users: { @@ -23,48 +27,26 @@ type UsersListPageProps = Readonly<{ lastPage: number; }; keyWord: string; + institutions: InstitutionModel[]; + profiles: ProfilModel[]; + roles: RoleModel[]; + institution: number; + profile: number; + role: number; }>; -export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { +export const UsersListPage = ({ users, keyWord, institutions, profiles, roles, institution, profile, role }: UsersListPageProps) => { const [userData, setUserData] = useState(users.data); const [lastPage, setLastPage] = useState(users.lastPage); - const [key, setKey] = useQueryState("key", parseAsString.withDefault(keyWord)); - + const [institutionId, setInstitutionId] = useQueryState("institutionId", parseAsInteger.withDefault(institution)); + const [profileId, setProfileId] = useQueryState("profileId", parseAsInteger.withDefault(profile)); + const [roleId, setRoleId] = useQueryState("roleId", parseAsInteger.withDefault(role)); const [page, setPage] = useQueryState("page", parseAsInteger.withDefault(users.currentPage)); const { wording } = useDependencies(); - const Profiles = [ - { profil_label: "Utilisateur lambda", profil_code: "f998021c-9613-4978-be6a-2b4cd9e24ffb" }, - { profil_label: "Equipe projet", profil_code: "4bbf1e31-180a-4d29-9973-54459dc3087d" }, - ]; - - const Institutions = [ - { inst_code_geo: "84", inst_libelle: "ARS Auvergne-Rhône-Alpes", inst_code: "ARS_84" }, - { inst_code_geo: "27", inst_libelle: "ARS Bourgogne-Franche-Comté", inst_code: "ARS_27" }, - { inst_code_geo: "53", inst_libelle: "ARS Bretagne", inst_code: "ARS_53" }, - { inst_code_geo: "24", inst_libelle: "ARS Centre-Val de Loire", inst_code: "ARS_24" }, - { inst_code_geo: "94", inst_libelle: "ARS Corse", inst_code: "ARS_94" }, - { inst_code_geo: "44", inst_libelle: "ARS Grand Est", inst_code: "ARS_44" }, - { inst_code_geo: "1", inst_libelle: "ARS Guadeloupe", inst_code: "ARS_01" }, - { inst_code_geo: "3", inst_libelle: "ARS Guyane", inst_code: "ARS_03" }, - { inst_code_geo: "32", inst_libelle: "ARS Hauts-de-France", inst_code: "ARS_32" }, - { inst_code_geo: "11", inst_libelle: "ARS Île-de-France", inst_code: "ARS_11" }, - { inst_code_geo: "4", inst_libelle: "ARS La Réunion", inst_code: "ARS_04" }, - { inst_code_geo: "2", inst_libelle: "ARS Martinique", inst_code: "ARS_02" }, - { inst_code_geo: "6", inst_libelle: "ARS Mayotte", inst_code: "ARS_06" }, - { inst_code_geo: "28", inst_libelle: "ARS Normandie", inst_code: "ARS_28" }, - { inst_code_geo: "75", inst_libelle: "ARS Nouvelle-Aquitaine", inst_code: "ARS_75" }, - { inst_code_geo: "76", inst_libelle: "ARS Occitanie", inst_code: "ARS_76" }, - { inst_code_geo: "52", inst_libelle: "ARS Pays de la Loire", inst_code: "ARS_52" }, - { inst_code_geo: "93", inst_libelle: "ARS Provence-Alpes-Côte d`Azur", inst_code: "ARS_93" }, - { inst_code_geo: "0", inst_libelle: "DNUM (SCN)", inst_code: "SCN" }, - { inst_code_geo: "75", inst_libelle: "CAT-AMANIA", inst_code: "CAT" }, - { inst_code_geo: "44", inst_libelle: "TEST", inst_code: "TEST" }, - ]; - return (
    {userData && ( @@ -74,7 +56,7 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => {
    - + @@ -82,51 +64,22 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => {
    -
    -
    - - -
    - -
    - - -
    - -
    - - -
    -
    +
    @@ -145,8 +98,8 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { {wording.EMAIL} - {wording.ROLE_} {wording.INSTITUTION} + {wording.ROLE_} {wording.PROFILE} {wording.CREATION_DATE} @@ -169,23 +122,23 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => { {user.email} + {user.institution.libelle} + {user.role.libelle} - {user.institution.libelle} - {user.profils.map((profil: string) => { - const pr = Profiles.filter((item) => item.profil_code === profil); + const pr = profiles.filter((item) => item.code === profil); return ( -
    +
    - {pr[0].profil_label} + {pr[0].label}
    ); @@ -198,13 +151,13 @@ export const UsersListPage = ({ users, keyWord }: UsersListPageProps) => {
    diff --git a/src/pages/api/utilisateurs/getUsers.ts b/src/pages/api/utilisateurs/getUsers.ts index 7cdb8fdcf..772632ff5 100644 --- a/src/pages/api/utilisateurs/getUsers.ts +++ b/src/pages/api/utilisateurs/getUsers.ts @@ -11,7 +11,15 @@ export default async function handler(request: NextApiRequest, response: NextApi const key = request.query["key"] as string | ""; const sort = request.query["sort"] as string | ""; const page = request.query["page"] as number | 1; - const users = await getUsersListPaginatedEndpoint(dependencies, key, sort, page); + + const institutionId = request.query["institutionId"] as number | 0; + + console.log("777777777777777---->", institutionId); + console.log("888888888888888888---->", typeof institutionId); + const roleId = request.query["roleId"]; + const profilId = request.query["profilId"] as string | ""; + + const users = await getUsersListPaginatedEndpoint(dependencies, key, sort, page, institutionId, roleId, profilId); return response.status(200).json(users); } catch (error) { diff --git a/src/pages/settings/users/index.tsx b/src/pages/settings/users/index.tsx index c401da580..6d437d91e 100644 --- a/src/pages/settings/users/index.tsx +++ b/src/pages/settings/users/index.tsx @@ -1,6 +1,12 @@ import { GetStaticPropsResult } from "next"; +import { InstitutionModel } from "../../../../database/models/InstitutionModel"; +import { ProfilModel } from "../../../../database/models/ProfilModel"; +import { RoleModel } from "../../../../database/models/RoleModel"; import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; +import { getAllProfilesEndpoint } from "../../../backend/infrastructure/controllers/getAllProfilesEndpoint"; +import { getAllRolesEndpoint } from "../../../backend/infrastructure/controllers/getAllRolesEndpoint"; +import { getInstitutionsEndpoint } from "../../../backend/infrastructure/controllers/getInstitutionsEndpoint"; import { getUsersListPaginatedEndpoint } from "../../../backend/infrastructure/controllers/getUsersListPaginatedEndpoint"; import { dependencies } from "../../../backend/infrastructure/dependencies"; import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; @@ -15,9 +21,18 @@ interface IUsersPaginatedList { lastPage: number; } -type RouterProps = Readonly<{ usersPaginatedList: IUsersPaginatedList; keyWord: string }>; +type RouterProps = Readonly<{ + usersPaginatedList: IUsersPaginatedList; + keyWord: string; + institutions: InstitutionModel[]; + profiles: ProfilModel[]; + roles: RoleModel[]; + institution: number; + profile: number; + role: number; +}>; -export default function Router({ usersPaginatedList, keyWord }: RouterProps) { +export default function Router({ usersPaginatedList, keyWord, institutions, profiles, roles, institution, profile, role }: RouterProps) { const { wording } = useDependencies(); useBreadcrumb([ @@ -26,20 +41,52 @@ export default function Router({ usersPaginatedList, keyWord }: RouterProps) { path: "", }, ]); - return ; + return ( + + ); } export async function getServerSideProps(context): Promise> { try { - let { page, key } = context.query; + let { page, key, institution, role, profil, institutionId, roleId, profilId } = context.query; page = page as number | 1; key = key as string | ""; + institutionId = institutionId as number | 0; + roleId = roleId as number | 0; + profilId = profilId as string | ""; - const users = await getUsersListPaginatedEndpoint(dependencies, key, "Desc", page); - + const users = await getUsersListPaginatedEndpoint(dependencies, key, "Desc", page, institutionId, roleId, profilId); console.log("--users---", users); + + const institutions = await getInstitutionsEndpoint(dependencies); + console.log("--institutions---" /*, institutions*/); + + const profiles = await getAllProfilesEndpoint(dependencies); + console.log("--profiles---" /*, profiles*/); + + const roles = await getAllRolesEndpoint(dependencies); + console.log("--roles---" /*, roles*/); + return { - props: { usersPaginatedList: JSON.parse(JSON.stringify(users)), keyWord: key || "" }, + props: { + usersPaginatedList: JSON.parse(JSON.stringify(users)), + keyWord: key || "", + institutions: JSON.parse(JSON.stringify(institutions)), + profiles: JSON.parse(JSON.stringify(profiles)), + roles: JSON.parse(JSON.stringify(roles)), + institution: institution || 0, + role: role || 0, + profil: profil || 0, + }, }; } catch (error) { throw error; From 132f54ec7d0561e927a18de3c842e182d37b34c2 Mon Sep 17 00:00:00 2001 From: Adolato Date: Thu, 23 Nov 2023 13:21:07 +0100 Subject: [PATCH 11/67] (hel-537) hel-537/page-admin --- .../TypeOrmUtilisateurLoader.ts | 10 +- .../Filter/AdvancedFilter/AdvancedFilter.tsx | 99 +++++++++++++++---- .../UsersListPage/UsersListPage.tsx | 4 +- src/pages/api/utilisateurs/getUsers.ts | 8 +- src/pages/settings/users/index.tsx | 4 +- 5 files changed, 93 insertions(+), 32 deletions(-) diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index ae6e8793c..d892654fa 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -2,7 +2,7 @@ import { compare, genSalt, hash } from "bcrypt"; import { createHash } from "crypto"; import fs from "fs"; import path from "path"; -import { DataSource, ILike, Like } from "typeorm"; +import { DataSource, ILike } from "typeorm"; import { InstitutionModel } from "../../../../../database/models/InstitutionModel"; import { ProfilModel } from "../../../../../database/models/ProfilModel"; @@ -138,7 +138,7 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { } let roleCondition = {}; - if (profilId) { + if (roleId) { roleCondition = { role: { id: roleId } }; } @@ -156,11 +156,7 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { ]; const currentPageA: number = parseInt(currentPage as any) || 1; - const take = 5; - - console.log("99999999999999999999-----"); - - console.log(conditions); + const take = 50; const total = await utilisateurRepo.countBy(conditions); diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx index 181bd7b24..b8ab544b0 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx @@ -11,17 +11,17 @@ import styles from "./AdvancedFilter.module.css"; type KeyWordFilterProps = Readonly<{ keyWord: string; - setKey: () => {}; - setUserData: () => {}; - setPage: () => {}; - setLastPage: () => {}; + setKey: () => void; + setUserData: () => void; + setPage: () => void; + setLastPage: () => void; + setRoleId: () => void; institutions: InstitutionModel[]; profiles: ProfilModel[]; roles: RoleModel[]; - profileId: number; + profileId: string; roleId: number; - setRoleId: number; }>; export const AdvancedFilter = ({ @@ -42,16 +42,80 @@ export const AdvancedFilter = ({ key, page, }: KeyWordFilterProps) => { - async function handleChangeInstitution(e: React.ChangeEvent) { + async function handleChangeInstitution(e: React.ChangeEvent /*, roleId: number, profileId: string*/) { e.preventDefault(); - console.log("onChange TextInput value: " + e.target.value); + // console.log("onChange TextInput value: " + e.target.value); const keyValue = key ? key : ""; - console.log("key--------------: " + key); + // console.log("key--------------: " + key); setInstitutionId(e.target.value); - const params = { key: keyValue, sort: "", page: page, institutionId: e.target.value }; - await fetch("/api/utilisateurs/getUsers?" + new URLSearchParams(params).toString(), { + const institutionCondition = { institutionId: e.target.value }; + + let roleCondition = {}; + if (roleId) { + roleCondition = { roleId: roleId }; + } + + let profilCondition = {}; + if (profileId) { + profilCondition = { profileId: profileId }; + } + + const params = { key: keyValue, sort: "", page: page, ...institutionCondition, ...roleCondition, ...profilCondition }; + getUsersAction(params); + } + + async function handleChangeRole(e: React.ChangeEvent /*, institutionId: number, profileId: string*/) { + e.preventDefault(); + + // console.log("onChange TextInput value: " + e.target.value); + const keyValue = key ? key : ""; + // console.log("key--------------: " + key); + setRoleId(e.target.value); + + let institutionCondition = {}; + if (institutionId) { + institutionCondition = { institutionId: institutionId }; + } + + const roleCondition = { roleId: e.target.value }; + + let profilCondition = {}; + if (profileId) { + profilCondition = { profileId: profileId }; + } + + const params = { key: keyValue, sort: "", page: page, ...institutionCondition, ...roleCondition, ...profilCondition }; + getUsersAction(params); + } + + async function handleChangeProfil(e: React.ChangeEvent /*, institutionId: number, roleId: number*/) { + e.preventDefault(); + + console.log("onChange TextInput value: profil code" + e.target.value); + const keyValue = key ? key : ""; + // console.log("key--------------: " + key); + setProfileId(e.target.value); + + let institutionCondition = {}; + if (institutionId) { + institutionCondition = { institutionId: institutionId }; + } + + let roleCondition = {}; + if (roleId) { + roleCondition = { roleId: roleId }; + } + + const profilCondition = { profileId: e.target.value }; + + const params = { key: keyValue, sort: "", page: page, ...institutionCondition, ...roleCondition, ...profilCondition }; + getUsersAction(params); + } + + function getUsersAction(params: {}) { + fetch("/api/utilisateurs/getUsers?" + new URLSearchParams(params).toString(), { headers: { "Content-Type": "application/json" }, method: "GET", }) @@ -86,13 +150,14 @@ export const AdvancedFilter = ({ - handleChangeRole(e)}> + {roles.map((item) => ( - ))} @@ -103,13 +168,13 @@ export const AdvancedFilter = ({ - handleChangeProfil(e)}> + {profiles.map((item) => ( - ))} diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx index 1ef12674b..f9ff0756f 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx @@ -32,7 +32,7 @@ type UsersListPageProps = Readonly<{ roles: RoleModel[]; institution: number; profile: number; - role: number; + role: string; }>; export const UsersListPage = ({ users, keyWord, institutions, profiles, roles, institution, profile, role }: UsersListPageProps) => { @@ -42,7 +42,7 @@ export const UsersListPage = ({ users, keyWord, institutions, profiles, roles, i const [key, setKey] = useQueryState("key", parseAsString.withDefault(keyWord)); const [institutionId, setInstitutionId] = useQueryState("institutionId", parseAsInteger.withDefault(institution)); const [profileId, setProfileId] = useQueryState("profileId", parseAsInteger.withDefault(profile)); - const [roleId, setRoleId] = useQueryState("roleId", parseAsInteger.withDefault(role)); + const [roleId, setRoleId] = useQueryState("roleId", parseAsString.withDefault(role)); const [page, setPage] = useQueryState("page", parseAsInteger.withDefault(users.currentPage)); const { wording } = useDependencies(); diff --git a/src/pages/api/utilisateurs/getUsers.ts b/src/pages/api/utilisateurs/getUsers.ts index 772632ff5..69dcedab2 100644 --- a/src/pages/api/utilisateurs/getUsers.ts +++ b/src/pages/api/utilisateurs/getUsers.ts @@ -13,11 +13,11 @@ export default async function handler(request: NextApiRequest, response: NextApi const page = request.query["page"] as number | 1; const institutionId = request.query["institutionId"] as number | 0; - - console.log("777777777777777---->", institutionId); - console.log("888888888888888888---->", typeof institutionId); const roleId = request.query["roleId"]; - const profilId = request.query["profilId"] as string | ""; + const profilId = request.query["profileId"] as string | ""; + + console.log("777777777777777---->", profilId); + console.log("888888888888888888---->", typeof profilId); const users = await getUsersListPaginatedEndpoint(dependencies, key, sort, page, institutionId, roleId, profilId); diff --git a/src/pages/settings/users/index.tsx b/src/pages/settings/users/index.tsx index 6d437d91e..b6ca300d5 100644 --- a/src/pages/settings/users/index.tsx +++ b/src/pages/settings/users/index.tsx @@ -29,7 +29,7 @@ type RouterProps = Readonly<{ roles: RoleModel[]; institution: number; profile: number; - role: number; + role: string; }>; export default function Router({ usersPaginatedList, keyWord, institutions, profiles, roles, institution, profile, role }: RouterProps) { @@ -84,7 +84,7 @@ export async function getServerSideProps(context): Promise Date: Thu, 23 Nov 2023 15:00:26 +0100 Subject: [PATCH 12/67] (hel-537) hel-537/page-admin --- .../Filter/AdvancedFilter/AdvancedFilter.tsx | 18 ++++++++++-------- .../UsersListPage/UsersListPage.tsx | 8 ++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx index b8ab544b0..e48f43c08 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx @@ -16,6 +16,8 @@ type KeyWordFilterProps = Readonly<{ setPage: () => void; setLastPage: () => void; setRoleId: () => void; + setProfileId: () => void; + setInstitutionId: () => void; institutions: InstitutionModel[]; profiles: ProfilModel[]; @@ -135,8 +137,8 @@ export const AdvancedFilter = ({ handleChangeRole(e)}> - {roles.map((item) => ( - ))} @@ -169,8 +171,8 @@ export const AdvancedFilter = ({ Profil - - - {Institutions.map((item) => ( -
    )} diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx index d15aad0b9..e56195197 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/UsersListPage.tsx @@ -4,6 +4,8 @@ import "@gouvfr/dsfr/dist/component/table/table.min.css"; import "@gouvfr/dsfr/dist/component/select/select.min.css"; +import "@gouvfr/dsfr/dist/component/alert/alert.min.css"; + import { useQueryState, parseAsInteger, parseAsString } from "next-usequerystate"; import { useState } from "react"; @@ -33,9 +35,10 @@ type UsersListPageProps = Readonly<{ institution: number; profile: string; role: number; + status: string; }>; -export const UsersListPage = ({ users, keyWord, institutions, profiles, roles, institution, profile, role }: UsersListPageProps) => { +export const UsersListPage = ({ users, keyWord, institutions, profiles, roles, institution, profile, role, status }: UsersListPageProps) => { const [userData, setUserData] = useState(users.data); const [lastPage, setLastPage] = useState(users.lastPage); @@ -44,6 +47,7 @@ export const UsersListPage = ({ users, keyWord, institutions, profiles, roles, i const [roleId, setRoleId] = useQueryState("roleId", parseAsInteger.withDefault(role)); const [profileId, setProfileId] = useQueryState("profileId", parseAsString.withDefault(profile)); const [page, setPage] = useQueryState("page", parseAsInteger.withDefault(users.currentPage)); + const [statusCode, setStatusCode] = useQueryState("status", parseAsString.withDefault(status)); const { wording } = useDependencies(); @@ -51,8 +55,19 @@ export const UsersListPage = ({ users, keyWord, institutions, profiles, roles, i
    {userData && ( <> -

    {wording.PAGE_UTILISATEUR_TITRE}

    -
    +

    {wording.PAGE_UTILISATEUR_TITRE}

    + + {statusCode === "edit_successfully" && ( +
    +

    La modification de l'utilisateur a été effectuée avec succès.

    +
    + )} + + {statusCode === "deleted_successfully" && ( +
    +

    La suppression de l'utilisateur a été effectuée avec succès.

    +
    + )}
    diff --git a/src/pages/api/profile/add.ts b/src/pages/api/profile/add.ts index 0cf8fd0df..147ce8e83 100644 --- a/src/pages/api/profile/add.ts +++ b/src/pages/api/profile/add.ts @@ -6,23 +6,20 @@ import { dependencies } from "../../../backend/infrastructure/dependencies"; import { checkAdminRole } from "../../../checkAdminMiddleware"; const handler = async (request: NextApiRequest, response: NextApiResponse) => { - try { - if (request.method !== "POST") { - response.status(405).send("Method not allowed"); - } - const { label, value } = request.body; - const recherche = await addProfileEndpoint(dependencies, label, value); - return response.status(200).json(recherche); - - } catch (error) { - return response.status(500); + try { + if (request.method !== "POST") { + response.status(405).send("Method not allowed"); } - -} - + const { label, value } = request.body; + const recherche = await addProfileEndpoint(dependencies, label, value); + return response.status(200).json(recherche); + } catch (error) { + return response.status(500); + } +}; export default async (req: NextApiRequest, res: NextApiResponse) => { - if (await checkAdminRole(req, res)) { - await handler(req, res); - } + if (await checkAdminRole(req, res)) { + await handler(req, res); + } }; diff --git a/src/pages/api/utilisateurs/update.ts b/src/pages/api/utilisateurs/update.ts new file mode 100644 index 000000000..845cdc542 --- /dev/null +++ b/src/pages/api/utilisateurs/update.ts @@ -0,0 +1,25 @@ +/* eslint-disable import/no-anonymous-default-export */ +import { NextApiRequest, NextApiResponse } from "next"; + +import { updateUserEndpoint } from "../../../backend/infrastructure/controllers/updateUserEndpoint"; +import { dependencies } from "../../../backend/infrastructure/dependencies"; +import { checkAdminRole } from "../../../checkAdminMiddleware"; + +const handler = async (request: NextApiRequest, response: NextApiResponse) => { + try { + if (request.method !== "POST") { + response.status(405).send("Method not allowed"); + } + const { userCode, roleCode, institutionCode, profilsCode } = request.body; + const recherche = await updateUserEndpoint(dependencies, userCode, roleCode, institutionCode, profilsCode); + return response.status(200).json(recherche); + } catch (error) { + return response.status(500); + } +}; + +export default async (req: NextApiRequest, res: NextApiResponse) => { + //if (await checkAdminRole(req, res)) { + await handler(req, res); + // } +}; diff --git a/src/pages/settings/users/[userCode].tsx b/src/pages/settings/users/[userCode].tsx index cb8931cd2..e39d499f5 100644 --- a/src/pages/settings/users/[userCode].tsx +++ b/src/pages/settings/users/[userCode].tsx @@ -1,6 +1,12 @@ import { GetStaticPathsResult, GetStaticPropsResult } from "next"; +import { InstitutionModel } from "../../../../database/models/InstitutionModel"; -import { ProfileValue } from "../../../../database/models/ProfilModel"; +import { ProfilModel } from "../../../../database/models/ProfilModel"; +import { RoleModel } from "../../../../database/models/RoleModel"; +import { UtilisateurModel } from "../../../../database/models/UtilisateurModel"; +import { getAllProfilesEndpoint } from "../../../backend/infrastructure/controllers/getAllProfilesEndpoint"; +import { getAllRolesEndpoint } from "../../../backend/infrastructure/controllers/getAllRolesEndpoint"; +import { getInstitutionsEndpoint } from "../../../backend/infrastructure/controllers/getInstitutionsEndpoint"; import { getUserByCodeEndpoint } from "../../../backend/infrastructure/controllers/getUserByCodeEndpoint"; import { dependencies } from "../../../backend/infrastructure/dependencies"; import { useDependencies } from "../../../frontend/ui/commun/contexts/useDependencies"; @@ -8,10 +14,13 @@ import { useBreadcrumb } from "../../../frontend/ui/commun/hooks/useBreadcrumb"; import { EditUser } from "../../../frontend/ui/parametrage-utilisateurs/EditUser/EditUser"; type RouterProps = Readonly<{ - user: any; + users: UtilisateurModel; + institutions: InstitutionModel[]; + profiles: ProfilModel[]; + roles: RoleModel[]; }>; -export default function Router({ user }: RouterProps) { +export default function Router({ user, institutions, profiles, roles }: RouterProps) { const { wording } = useDependencies(); useBreadcrumb([ { @@ -25,17 +34,10 @@ export default function Router({ user }: RouterProps) { ]); // return ; //return <>okkkkkkkkkkkkk user code est : {userCode}; - return ; + return ; } -export function getStaticPaths(): GetStaticPathsResult { - return { - fallback: "blocking", - paths: [], - }; -} - -export async function getStaticProps({ params }: { params: { userCode: string } }): Promise> { +export async function getServerSideProps({ params }: { params: { userCode: string } }): Promise> { try { const { environmentVariables } = dependencies; const user = await getUserByCodeEndpoint(dependencies, params.userCode); @@ -47,12 +49,22 @@ export async function getStaticProps({ params }: { params: { userCode: string } }; } + const institutions = await getInstitutionsEndpoint(dependencies); + //console.log("--institutions---", institutions); + + const profiles = await getAllProfilesEndpoint(dependencies); + // console.log("--profiles---", profiles); + + const roles = await getAllRolesEndpoint(dependencies); + // console.log("--roles---", roles); + return { props: { user: JSON.parse(JSON.stringify(user)), + institutions: JSON.parse(JSON.stringify(institutions)), + profiles: JSON.parse(JSON.stringify(profiles)), + roles: JSON.parse(JSON.stringify(roles)), }, - - revalidate: Number(environmentVariables.TIME_OF_CACHE_PAGE), }; } catch (error) { throw error; diff --git a/src/pages/settings/users/index.tsx b/src/pages/settings/users/index.tsx index 7a50c64b9..9e345d531 100644 --- a/src/pages/settings/users/index.tsx +++ b/src/pages/settings/users/index.tsx @@ -30,9 +30,10 @@ type RouterProps = Readonly<{ institution: number; profile: number; role: string; + status: string; }>; -export default function Router({ usersPaginatedList, keyWord, institutions, profiles, roles, institution, profile, role }: RouterProps) { +export default function Router({ usersPaginatedList, keyWord, institutions, profiles, roles, institution, profile, role, status }: RouterProps) { const { wording } = useDependencies(); useBreadcrumb([ @@ -57,31 +58,31 @@ export default function Router({ usersPaginatedList, keyWord, institutions, prof export async function getServerSideProps(context): Promise> { try { - let { page, key, institution, role, profil, institutionId, roleId, profileId } = context.query; + let { page, key, institution, role, profil, institutionId, roleId, profileId, status } = context.query; page = page as number | 1; key = key as string | ""; institutionId = institutionId as number | 0; roleId = roleId as number | 0; const profilId = profileId as string | ""; - console.log("---------------CCCC------------"); - console.log(context.query); - console.log("---------------------A-------------------"); - console.log("institutionId : ", institutionId); - console.log("roleId : ", roleId); - console.log("profilId : ", profileId); + // console.log("---------------CCCC------------"); + // console.log(context.query); + // console.log("---------------------A-------------------"); + // console.log("institutionId : ", institutionId); + // console.log("roleId : ", roleId); + // console.log("profilId : ", profileId); const users = await getUsersListPaginatedEndpoint(dependencies, key, "Desc", page, institutionId, roleId, profilId); - console.log("--users---", users); + //console.log("--users---", users); const institutions = await getInstitutionsEndpoint(dependencies); - console.log("--institutions---" /*, institutions*/); + // console.log("--institutions---" /*, institutions*/); const profiles = await getAllProfilesEndpoint(dependencies); - console.log("--profiles---" /*, profiles*/); + // console.log("--profiles---" /*, profiles*/); const roles = await getAllRolesEndpoint(dependencies); - console.log("--roles---" /*, roles*/); + // console.log("--roles---" /*, roles*/); return { props: { @@ -93,6 +94,7 @@ export async function getServerSideProps(context): Promise Date: Tue, 28 Nov 2023 11:35:16 +0100 Subject: [PATCH 17/67] (hel-537) hel-537/page-admin --- .../Filter/AdvancedFilter/AdvancedFilter.tsx | 18 +++------------- .../UsersListPage/UsersListPage.tsx | 21 ++++++++++++------- src/pages/_app.tsx | 14 ++++++------- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx index 572006fae..0214b28a9 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx @@ -42,14 +42,10 @@ export const AdvancedFilter = ({ profileId, roleId, setRoleId, - key, page, }: KeyWordFilterProps) => { async function handleChangeInstitution(e: React.ChangeEvent) { e.preventDefault(); - - const keyValue = key ? key : ""; - setInstitutionId(e.target.value); const institutionCondition = { institutionId: e.target.value }; @@ -64,15 +60,12 @@ export const AdvancedFilter = ({ profilCondition = { profileId: profileId }; } - const params = { key: keyValue, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; + const params = { key: keyWord, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; getUsersAction(params); } async function handleChangeRole(e: React.ChangeEvent) { e.preventDefault(); - - const keyValue = key ? key : ""; - setRoleId(e.target.value); let institutionCondition = {}; @@ -87,16 +80,12 @@ export const AdvancedFilter = ({ profilCondition = { profileId: profileId }; } - const params = { key: keyValue, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; + const params = { key: keyWord, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; getUsersAction(params); } async function handleChangeProfil(e: React.ChangeEvent) { e.preventDefault(); - - console.log("onChange TextInput value: profil code" + e.target.value); - const keyValue = key ? key : ""; - setProfileId(e.target.value); let institutionCondition = {}; @@ -111,7 +100,7 @@ export const AdvancedFilter = ({ const profilCondition = { profileId: e.target.value }; - const params = { key: keyValue, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; + const params = { key: keyWord, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; getUsersAction(params); } @@ -164,7 +153,6 @@ export const AdvancedFilter = ({ ))}
    -
    ); }; diff --git a/src/pages/settings/users/index.tsx b/src/pages/settings/users/index.tsx index 9e345d531..922bd8119 100644 --- a/src/pages/settings/users/index.tsx +++ b/src/pages/settings/users/index.tsx @@ -31,9 +31,21 @@ type RouterProps = Readonly<{ profile: number; role: string; status: string; + lastElementInPage: boolean; }>; -export default function Router({ usersPaginatedList, keyWord, institutions, profiles, roles, institution, profile, role, status }: RouterProps) { +export default function Router({ + usersPaginatedList, + keyWord, + institutions, + profiles, + roles, + institution, + profile, + role, + status, + lastElementInPage, +}: RouterProps) { const { wording } = useDependencies(); useBreadcrumb([ @@ -52,6 +64,7 @@ export default function Router({ usersPaginatedList, keyWord, institutions, prof role={role} roles={roles} users={usersPaginatedList} + lastElementInPage={lastElementInPage} /> ); } @@ -72,9 +85,14 @@ export async function getServerSideProps(context): Promise Date: Fri, 1 Dec 2023 17:45:35 +0100 Subject: [PATCH 21/67] (hel-537) hel-537/page-admin --- .../getUsersListPaginatedEndpoint.ts | 5 +- .../TypeOrmUtilisateurLoader.ts | 20 +- .../gateways/UtilisateurLoader.ts" | 10 +- .../use-cases/UtilisateursUseCase.ts" | 12 +- .../AdvancedFilter/AdvancedFilter.module.css | 12 +- .../Filter/AdvancedFilter/AdvancedFilter.tsx | 34 +++- .../KeyWordFilter/KeyWordFilter.module.css | 6 - .../Filter/KeyWordFilter/KeyWordFilter.tsx | 51 ++++- .../ItemsPerPage/ItemsPerPage.module.css | 0 .../Pagination/ItemsPerPage/ItemsPerPage.tsx | 100 ++++++++++ .../PaginationBtn/PaginationBtn.module.css | 3 +- .../PaginationBtn/PaginationBtn.tsx | 178 ++++++++++++++++++ .../PaginationBtn/PaginationBtn.tsx | 152 --------------- .../UsersListPage/UsersListPage.module.css | 23 ++- .../UsersListPage/UsersListPage.tsx | 120 +++++++----- src/pages/api/utilisateurs/getUsers.ts | 3 +- src/pages/settings/users/index.tsx | 9 +- 17 files changed, 500 insertions(+), 238 deletions(-) create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/Pagination/ItemsPerPage/ItemsPerPage.module.css create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/Pagination/ItemsPerPage/ItemsPerPage.tsx rename src/frontend/ui/parametrage-utilisateurs/UsersListPage/{ => Pagination}/PaginationBtn/PaginationBtn.module.css (96%) create mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/Pagination/PaginationBtn/PaginationBtn.tsx delete mode 100644 src/frontend/ui/parametrage-utilisateurs/UsersListPage/PaginationBtn/PaginationBtn.tsx diff --git a/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts b/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts index 264a9b08f..33e8a261f 100644 --- a/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts +++ b/src/backend/infrastructure/controllers/getUsersListPaginatedEndpoint.ts @@ -9,11 +9,12 @@ export async function getUsersListPaginatedEndpoint( pdescrtion: number, institutionId: number, roleId: number, - profilId: string + profilId: string, + itemsPerPage: number ): Promise { try { const UtilisateurUseCase = new UtilisateursUseCase(dependencies.utilisateurLoader); - return await UtilisateurUseCase.getUsersListPaginated(key, sort, pdescrtion, institutionId, roleId, profilId); + return await UtilisateurUseCase.getUsersListPaginated(key, sort, pdescrtion, institutionId, roleId, profilId, itemsPerPage); } catch (error) { dependencies.logger.error(error); throw error; diff --git a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts index 501cc7138..33faf1be5 100644 --- a/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts +++ b/src/backend/infrastructure/gateways/utilisateur-loader/TypeOrmUtilisateurLoader.ts @@ -123,7 +123,15 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { return profiles; } - async getUsersListPaginated(key = "", sort: string, currentPage: number, institutionId: number, roleId: number, profilId: string): Promise { + async getUsersListPaginated( + key = "", + sort: string, + currentPage: number, + institutionId: number, + roleId: number, + profilId: string, + itemsPerPage: number + ): Promise { // return await (await this.orm).getRepository(UtilisateurModel).find(); const utilisateurRepo = (await this.orm).getRepository(UtilisateurModel); @@ -133,17 +141,17 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { const profilCondition = { profils: ["4bbf1e31-180a-4d29-9973-54459dc3087d"] };*/ let institutionCondition = {}; - if (institutionId) { + if (institutionId > 0) { institutionCondition = { institution: { id: institutionId } }; } let roleCondition = {}; - if (roleId) { + if (roleId > 0) { roleCondition = { role: { id: roleId } }; } let profilCondition = {}; - if (profilId) { + if (profilId && profilId.length > 0) { profilCondition = { profils: ArrayContains([profilId]) }; } @@ -156,7 +164,8 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { ]; const currentPageA: number = parseInt(currentPage as any) || 1; - const take = 3; + + const take = itemsPerPage || 10; const total = await utilisateurRepo.countBy(conditions); @@ -176,6 +185,7 @@ export class TypeOrmUtilisateurLoader implements UtilisateurLoader { keyWord: key, currentPage: currentPageA, lastPage: Math.ceil(total / take), + itemsPerPage: itemsPerPage, }; } diff --git "a/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" "b/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" index ba18bf491..e7a7b64f8 100644 --- "a/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" +++ "b/src/backend/m\303\251tier/gateways/UtilisateurLoader.ts" @@ -10,7 +10,15 @@ export interface UtilisateurLoader { createAccount(firstName: string, lastName: string, email: string, institution: string): Promise; getUserProfiles(codes: string[]): Promise; checkIfAdmin(userId: string): Promise; - getUsersListPaginated(key: string, sort: string, pdescrtion: number, institutionId: number, roleId: number, profilId: string): Promise; + getUsersListPaginated( + key: string, + sort: string, + pdescrtion: number, + institutionId: number, + roleId: number, + profilId: string, + itemsPerPage: number + ): Promise; getUserByCode(code: string): Promise; updateUser(userCode: string, roleCode: string, institutionCode: string, profilsCode: string[]): Promise; deleteUser(userCode: string): Promise; diff --git "a/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" "b/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" index e47fef8a3..69204ac14 100644 --- "a/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" +++ "b/src/backend/m\303\251tier/use-cases/UtilisateursUseCase.ts" @@ -4,8 +4,16 @@ import { UtilisateurLoader } from "../gateways/UtilisateurLoader"; export class UtilisateursUseCase { constructor(private utilisateurLoader: UtilisateurLoader) {} - async getUsersListPaginated(key: string, sort: string, pdescrtion: number, institutionId: number, roleId: number, profilId: string): Promise { - return await this.utilisateurLoader.getUsersListPaginated(key, sort, pdescrtion, institutionId, roleId, profilId); + async getUsersListPaginated( + key: string, + sort: string, + pdescrtion: number, + institutionId: number, + roleId: number, + profilId: string, + itemsPerPage: number + ): Promise { + return await this.utilisateurLoader.getUsersListPaginated(key, sort, pdescrtion, institutionId, roleId, profilId, itemsPerPage); } async getUserByCode(code: string): Promise { diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.module.css index 530077144..6a8aa5907 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.module.css +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.module.css @@ -1,3 +1,11 @@ -.filtre_details { - padding: 35px 150px; +.filter_details { + padding: 15px 15px 20px 15px; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; +} + +.filter-item { + width: 23%; } diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx index 0214b28a9..115a6d73d 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/AdvancedFilter/AdvancedFilter.tsx @@ -7,6 +7,7 @@ import "@gouvfr/dsfr/dist/component/select/select.min.css"; import { InstitutionModel } from "../../../../../../../database/models/InstitutionModel"; import { ProfilModel } from "../../../../../../../database/models/ProfilModel"; import { RoleModel } from "../../../../../../../database/models/RoleModel"; +import { KeyWordFilter } from "../KeyWordFilter/KeyWordFilter"; import styles from "./AdvancedFilter.module.css"; type KeyWordFilterProps = Readonly<{ @@ -18,6 +19,7 @@ type KeyWordFilterProps = Readonly<{ setRoleId: () => void; setProfileId: () => void; setInstitutionId: () => void; + setTotal: () => void; institutions: InstitutionModel[]; profiles: ProfilModel[]; @@ -25,11 +27,13 @@ type KeyWordFilterProps = Readonly<{ institutionId: number; roleId: number; profileId: string; + itemsPerPage: number; }>; export const AdvancedFilter = ({ keyWord, setKey, + setTotal, setUserData, setPage, setLastPage, @@ -43,6 +47,7 @@ export const AdvancedFilter = ({ roleId, setRoleId, page, + itemsPerPage, }: KeyWordFilterProps) => { async function handleChangeInstitution(e: React.ChangeEvent) { e.preventDefault(); @@ -60,7 +65,7 @@ export const AdvancedFilter = ({ profilCondition = { profileId: profileId }; } - const params = { key: keyWord, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; + const params = { key: keyWord, sort: "", page: 1, itemsPerPage: itemsPerPage, ...institutionCondition, ...roleCondition, ...profilCondition }; getUsersAction(params); } @@ -80,7 +85,7 @@ export const AdvancedFilter = ({ profilCondition = { profileId: profileId }; } - const params = { key: keyWord, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; + const params = { key: keyWord, sort: "", page: 1, itemsPerPage: itemsPerPage, ...institutionCondition, ...roleCondition, ...profilCondition }; getUsersAction(params); } @@ -100,7 +105,7 @@ export const AdvancedFilter = ({ const profilCondition = { profileId: e.target.value }; - const params = { key: keyWord, sort: "", page: 1, ...institutionCondition, ...roleCondition, ...profilCondition }; + const params = { key: keyWord, sort: "", page: 1, itemsPerPage: itemsPerPage, ...institutionCondition, ...roleCondition, ...profilCondition }; getUsersAction(params); } @@ -112,14 +117,29 @@ export const AdvancedFilter = ({ .then((response) => response.json()) .then((users) => { setUserData(users.data); + setTotal(users.total); setPage(1); setLastPage(users.lastPage); }); } return ( -
    -
    +
    +
    + +
    +
    @@ -136,7 +156,7 @@ export const AdvancedFilter = ({ ))}
    -
    +
    @@ -153,7 +173,7 @@ export const AdvancedFilter = ({ ))}
    -
    +
    diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.module.css b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.module.css index e06b23bfa..e69de29bb 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.module.css +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.module.css @@ -1,6 +0,0 @@ -.search-bar-container { - float: right; -} -.search-bar { - width: 350px; -} diff --git a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.tsx b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.tsx index af9e2fdee..2aaa1c3c5 100644 --- a/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.tsx +++ b/src/frontend/ui/parametrage-utilisateurs/UsersListPage/Filter/KeyWordFilter/KeyWordFilter.tsx @@ -9,18 +9,49 @@ import styles from "./KeyWordFilter.module.css"; type KeyWordFilterProps = Readonly<{ keyWord: string; - setKey: () => {}; - setUserData: () => {}; - setPage: () => {}; - setLastPage: () => {}; + itemsPerPage: number; + institutionId: number; + roleId: number; + profileId: string; + setKey: () => void; + setUserData: () => void; + setPage: () => void; + setLastPage: () => void; + setTotal: () => void; }>; -export const KeyWordFilter = ({ keyWord, setKey, setUserData, setPage, setLastPage }: KeyWordFilterProps) => { +export const KeyWordFilter = ({ + keyWord, + setKey, + setUserData, + setPage, + setLastPage, + setTotal, + itemsPerPage, + institutionId, + roleId, + profileId, +}: KeyWordFilterProps) => { async function handleChange(e: Event) { e.preventDefault(); setKey(e.target.value); - const params = { key: e.target.value, sort: "", page: 1 }; + let institutionCondition = {}; + if (institutionId) { + institutionCondition = { institutionId: institutionId }; + } + + let roleCondition = {}; + if (roleId) { + roleCondition = { roleId: roleId }; + } + + let profilCondition = {}; + if (profileId) { + profilCondition = { profileId: profileId }; + } + + const params = { key: e.target.value, sort: "", page: 1, itemsPerPage: itemsPerPage, ...institutionCondition, ...roleCondition, ...profilCondition }; await fetch("/api/utilisateurs/getUsers?" + new URLSearchParams(params).toString(), { headers: { "Content-Type": "application/json" }, method: "GET", @@ -29,12 +60,16 @@ export const KeyWordFilter = ({ keyWord, setKey, setUserData, setPage, setLastPa .then((users) => { setUserData(users.data); setPage(users.currentPage); + setTotal(users.total); setLastPage(users.lastPage); }); } return ( -
    -