From 20cb60be1618b6f07db2a4b818b5d1a29fc4e1fa Mon Sep 17 00:00:00 2001 From: GauthierWebDev Date: Wed, 23 Apr 2025 13:25:31 +0200 Subject: [PATCH] style: Improve code formatting for better readability --- app/components/PrevNextLinks.tsx | 173 +++--- app/components/Search.tsx | 541 ++++++++---------- .../certifications/dwwm/at2/cp7/+Page.mdx | 47 +- app/public/images/patterns/mvc.webp | Bin 0 -> 14720 bytes 4 files changed, 355 insertions(+), 406 deletions(-) create mode 100644 app/public/images/patterns/mvc.webp diff --git a/app/components/PrevNextLinks.tsx b/app/components/PrevNextLinks.tsx index c621d27..93b4f50 100644 --- a/app/components/PrevNextLinks.tsx +++ b/app/components/PrevNextLinks.tsx @@ -8,123 +8,102 @@ import { Link } from "@/components/Link"; import clsx from "clsx"; function ArrowIcon(props: JSX.IntrinsicElements["svg"]) { - return ( - - ); + return ( + + ); } type PageLinkProps = Omit & { - title: string; - href: string; - dir?: "previous" | "next"; + title: string; + href: string; + dir?: "previous" | "next"; }; function PageLink(props: PageLinkProps) { - const getPageCategory = () => - navigation.find((section) => { - return section.links.some( - (link) => - link.href === props.href || - link.subitems.some((subitem) => subitem.href === props.href), - ); - }); + const getPageCategory = () => + navigation.find((section) => { + return section.links.some( + (link) => link.href === props.href || link.subitems.some((subitem) => subitem.href === props.href), + ); + }); - return ( -
-
- {props.dir === "next" ? "Suivant" : "Précédent"} -
-
- -

- {getPageCategory() && ( - - {getPageCategory()?.title} - - )} - {props.title} -

- - -
-
- ); + return ( +
+
{props.dir === "next" ? "Suivant" : "Précédent"}
+
+ +

+ {getPageCategory() && ( + {getPageCategory()?.title} + )} + {props.title} +

+ + +
+
+ ); } export function PrevNextLinks() { - const pageContext = usePageContext(); + const pageContext = usePageContext(); - const allLinks = navigation - .sort((a, b) => { - // positions order (for sorting): - // 1. start - // 2. auto | undefined - // 3. end + const allLinks = navigation + .sort((a, b) => { + // positions order (for sorting): + // 1. start + // 2. auto | undefined + // 3. end - if (a.position === "start" && b.position !== "start") return -1; - if (a.position !== "start" && b.position === "start") return 1; + if (a.position === "start" && b.position !== "start") return -1; + if (a.position !== "start" && b.position === "start") return 1; - if (a.position === "end" && b.position !== "end") return 1; - if (a.position !== "end" && b.position === "end") return -1; + if (a.position === "end" && b.position !== "end") return 1; + if (a.position !== "end" && b.position === "end") return -1; - if (a.position === "auto" && b.position !== "auto") return -1; - if (a.position !== "auto" && b.position === "auto") return 1; + if (a.position === "auto" && b.position !== "auto") return -1; + if (a.position !== "auto" && b.position === "auto") return 1; - if (a.position === undefined && b.position !== undefined) return -1; - if (a.position !== undefined && b.position === undefined) return 1; - return 0; - }) - .flatMap((section) => section.links) - .flatMap((link) => { - return link.subitems ? [link, ...link.subitems] : link; - }); + if (a.position === undefined && b.position !== undefined) return -1; + if (a.position !== undefined && b.position === undefined) return 1; + return 0; + }) + .flatMap((section) => section.links) + .flatMap((link) => { + return link.subitems ? [link, ...link.subitems] : link; + }); - const getNeighboringLinks = () => { - const linkIndex = allLinks.findIndex( - (link) => link.href === pageContext.urlPathname, - ); - if (linkIndex === -1) return [null, null]; + const getNeighboringLinks = () => { + const linkIndex = allLinks.findIndex((link) => link.href === pageContext.urlPathname); + if (linkIndex === -1) return [null, null]; - const previousPage = allLinks[linkIndex - 1] || null; - let nextPage = allLinks[linkIndex + 1] || null; + const previousPage = allLinks[linkIndex - 1] || null; + let nextPage = allLinks[linkIndex + 1] || null; - if (nextPage?.href === pageContext.urlPathname) { - nextPage = allLinks[linkIndex + 2] || null; - } + if (nextPage?.href === pageContext.urlPathname) { + nextPage = allLinks[linkIndex + 2] || null; + } - return [previousPage, nextPage]; - }; + return [previousPage, nextPage]; + }; - if (getNeighboringLinks().length === 0) return null; + if (getNeighboringLinks().length === 0) return null; - return ( -
- {getNeighboringLinks()[0] && ( - - )} + return ( +
+ {getNeighboringLinks()[0] && } - {getNeighboringLinks()[1] && ( - - )} -
- ); + {getNeighboringLinks()[1] && ( + + )} +
+ ); } diff --git a/app/components/Search.tsx b/app/components/Search.tsx index 17bb85c..b5c6210 100644 --- a/app/components/Search.tsx +++ b/app/components/Search.tsx @@ -1,13 +1,7 @@ import type { SearchResult } from "@/services/FlexSearchService"; import type { JSX, Accessor, Setter } from "solid-js"; -import { - createContext, - useContext, - For, - createEffect, - createSignal, -} from "solid-js"; +import { createContext, useContext, For, createEffect, createSignal } from "solid-js"; import { Highlighter } from "solid-highlight-words"; import { useDebounce } from "@/hooks/useDebounce"; @@ -18,334 +12,305 @@ import { useId } from "@/hooks/useId"; import clsx from "clsx"; const SearchContext = createContext<{ - query: Accessor; - close: () => void; - results: Accessor; - isLoading: Accessor; - isOpened: Accessor; - setQuery: Setter; - setIsOpened: Setter; - setIsLoading: Setter; - setResults: Setter; + query: Accessor; + close: () => void; + results: Accessor; + isLoading: Accessor; + isOpened: Accessor; + setQuery: Setter; + setIsOpened: Setter; + setIsLoading: Setter; + setResults: Setter; }>({ - query: () => "", - close: () => {}, - results: () => [], - isLoading: () => false, - isOpened: () => false, - setQuery: () => {}, - setIsOpened: () => {}, - setIsLoading: () => {}, - setResults: () => {}, + query: () => "", + close: () => {}, + results: () => [], + isLoading: () => false, + isOpened: () => false, + setQuery: () => {}, + setIsOpened: () => {}, + setIsLoading: () => {}, + setResults: () => {}, }); function SearchIcon(props: JSX.IntrinsicElements["svg"]) { - return ( - - ); + return ( + + ); } function LoadingIcon(props: JSX.IntrinsicElements["svg"]) { - const id = useId(); + const id = useId(); - return ( - - ); + return ( + + ); } function SearchInput() { - const { close, setQuery, query, isLoading } = useContext(SearchContext); + const { close, setQuery, query, isLoading } = useContext(SearchContext); - return ( -
- - { - if (event.key === "Escape") { - // In Safari, closing the dialog with the escape key can sometimes cause the scroll position to jump to the - // bottom of the page. This is a workaround for that until we can figure out a proper fix in Headless UI. - if (document.activeElement instanceof HTMLElement) { - document.activeElement.blur(); - } + return ( +
+ + { + if (event.key === "Escape") { + // In Safari, closing the dialog with the escape key can sometimes cause the scroll position to jump to the + // bottom of the page. This is a workaround for that until we can figure out a proper fix in Headless UI. + if (document.activeElement instanceof HTMLElement) { + document.activeElement.blur(); + } - close(); - } - }} - value={query()} - onInput={(event) => { - const { value } = event.currentTarget; - setQuery(value); - }} - /> - {isLoading() && ( -
- -
- )} -
- ); + close(); + } + }} + value={query()} + onInput={(event) => { + const { value } = event.currentTarget; + setQuery(value); + }} + /> + {isLoading() && ( +
+ +
+ )} +
+ ); } function HighlightQuery(props: { text: string; query: string }) { - return ( - - ); + return ( + + ); } function SearchResultItem(props: { result: SearchResult; query: string }) { - const { close } = useContext(SearchContext); - const id = useId(); + const { close } = useContext(SearchContext); + const id = useId(); - const getHierarchy = (): string[] => { - const sectionTitle = navigation.find((section) => { - return section.links.find( - (link) => link.href === props.result.url.split("#")[0], - ); - })?.title; + const getHierarchy = (): string[] => { + const sectionTitle = navigation.find((section) => { + return section.links.find((link) => link.href === props.result.url.split("#")[0]); + })?.title; - return [sectionTitle, props.result.pageTitle].filter( - (x): x is string => typeof x === "string", - ); - }; + return [sectionTitle, props.result.pageTitle].filter((x): x is string => typeof x === "string"); + }; - return ( -
  • { - if (event.key === "Enter") { - navigate(props.result.url); - close(); - } - }} - onClick={() => { - navigate(props.result.url); - close(); - }} - > - - {getHierarchy().length > 0 && ( - - )} -
  • - ); + const handleNavigate = (url: string) => { + navigate(`/${url}`.replace(/\/+/g, "/")); + close(); + }; + + return ( +
  • { + if (event.key === "Enter") handleNavigate(props.result.url); + }} + onClick={() => handleNavigate(props.result.url)} + > + + {getHierarchy().length > 0 && ( + + )} +
  • + ); } function SearchResults() { - const { results, query } = useContext(SearchContext); + const { results, query } = useContext(SearchContext); - if (results().length === 0) { - return ( -

    - Aucun résultat pour “ - {query()} - ” -

    - ); - } + if (results().length === 0) { + return ( +

    + Aucun résultat pour “ + {query()} + ” +

    + ); + } - return ( -
      - - {(result) => ( -
    • - -
    • - )} -
      -
    - ); + return ( +
      + + {(result) => ( +
    • + +
    • + )} +
      +
    + ); } function SearchDialog(props: { class?: string }) { - const { close, isOpened, setIsOpened, results } = useContext(SearchContext); + const { close, isOpened, setIsOpened, results } = useContext(SearchContext); - createEffect(() => { - if (isOpened()) return; + createEffect(() => { + if (isOpened()) return; - function onKeyDown(event: KeyboardEvent) { - if (event.key === "k" && (event.metaKey || event.ctrlKey)) { - event.preventDefault(); - setIsOpened(true); - } - } + function onKeyDown(event: KeyboardEvent) { + if (event.key === "k" && (event.metaKey || event.ctrlKey)) { + event.preventDefault(); + setIsOpened(true); + } + } - window.addEventListener("keydown", onKeyDown); + window.addEventListener("keydown", onKeyDown); - return () => { - window.removeEventListener("keydown", onKeyDown); - }; - }, [isOpened, setIsOpened]); + return () => { + window.removeEventListener("keydown", onKeyDown); + }; + }, [isOpened, setIsOpened]); - const handleClickOutside = (event: MouseEvent) => { - const { target, currentTarget } = event; + const handleClickOutside = (event: MouseEvent) => { + const { target, currentTarget } = event; - if (target instanceof Node && currentTarget instanceof Node) { - if (target === currentTarget) close(); - } - }; + if (target instanceof Node && currentTarget instanceof Node) { + if (target === currentTarget) close(); + } + }; - return ( - <> - -
    + return ( + <> + +
    -
    { - if (event.key === "Escape") close(); - }} - > - -
    event.preventDefault()}> - -
    - {results().length > 0 && } -
    - -
    -
    -
    - - ); +
    { + if (event.key === "Escape") close(); + }} + > + +
    event.preventDefault()}> + +
    + {results().length > 0 && } +
    + +
    +
    +
    + + ); } export function Search() { - const [results, setResults] = createSignal([]); - const [modifierKey, setModifierKey] = createSignal(); - const [isLoading, setIsLoading] = createSignal(false); - const [isOpened, setIsOpened] = createSignal(false); - const [query, setQuery] = createSignal(""); + const [results, setResults] = createSignal([]); + const [modifierKey, setModifierKey] = createSignal(); + const [isLoading, setIsLoading] = createSignal(false); + const [isOpened, setIsOpened] = createSignal(false); + const [query, setQuery] = createSignal(""); - const debouncedQuery = useDebounce(query, 300); + const debouncedQuery = useDebounce(query, 300); - const onSearch = async (query: string) => { - const response = await fetch(`/search?query=${query}`); - if (!response.ok) { - throw new Error("Network response was not ok"); - } - const data = await response.json(); - return data; - }; + const onSearch = async (query: string) => { + const response = await fetch(`/search?query=${query}`); + if (!response.ok) { + throw new Error("Network response was not ok"); + } + const data = await response.json(); + return data; + }; - createEffect(() => { - const platform = navigator.userAgentData?.platform || navigator.platform; - setModifierKey(/(Mac|iPhone|iPod|iPad)/i.test(platform) ? "⌘" : "Ctrl "); - }, []); + createEffect(() => { + const platform = navigator.userAgentData?.platform || navigator.platform; + setModifierKey(/(Mac|iPhone|iPod|iPad)/i.test(platform) ? "⌘" : "Ctrl "); + }, []); - createEffect(() => { - const query = debouncedQuery(); + createEffect(() => { + const query = debouncedQuery(); - if (query.length === 0) { - setIsLoading(false); - setResults([]); - return; - } + if (query.length === 0) { + setIsLoading(false); + setResults([]); + return; + } - setIsLoading(true); + setIsLoading(true); - onSearch(query) - .then(setResults) - .finally(() => setIsLoading(false)); - }); + onSearch(query) + .then(setResults) + .finally(() => setIsLoading(false)); + }); - return ( - setIsOpened(false), - results, - isLoading, - isOpened, - setQuery, - setIsOpened, - setIsLoading, - setResults, - }} - > - - - - ); + return ( + setIsOpened(false), + results, + isLoading, + isOpened, + setQuery, + setIsOpened, + setIsLoading, + setResults, + }} + > + + + + ); } diff --git a/app/pages/certifications/dwwm/at2/cp7/+Page.mdx b/app/pages/certifications/dwwm/at2/cp7/+Page.mdx index d6c9c68..d6b04cb 100644 --- a/app/pages/certifications/dwwm/at2/cp7/+Page.mdx +++ b/app/pages/certifications/dwwm/at2/cp7/+Page.mdx @@ -30,39 +30,43 @@ Le design pattern MVC est un modèle d'architecture logicielle qui sépare les d - **Contrôleur** : fait le lien entre le modèle et la vue. Il contient la logique métier de l'application. - Il existe de nombreux schémas qui expliquent le design pattern MVC mais ils ne sont pas tous corrects. - Enfin, si, ils sont corrects... mais certains ne s'appliquent pas à tous les frameworks et architectures. + Il existe de nombreux schémas qui expliquent le design pattern MVC mais ils ne sont pas tous corrects. Enfin, si, ils + sont corrects... mais certains ne s'appliquent pas à tous les frameworks et architectures. Pour t'aider à mieux te représenter un schéma MVC avec les ordres de flux de données et de contrôle : -Schéma MVC pour une application web basique +Schéma MVC pour une application web basique La vue ne retourne pas directement au client car elle doit passer par le contrôleur. On ne s'en rend pas forcément compte, mais la vue est généralement générée par le contrôleur via un moteur de template _(EJS, Twig, etc.)_. - Une fois le HTML généré, le contrôleur s'occupe de l'envoyer dans la réponse HTTP au client. - C'est ce qui permet de garder une séparation entre la logique métier et l'interface utilisateur. +Une fois le HTML généré, le contrôleur s'occupe de l'envoyer dans la réponse HTTP au client. + C'est ce qui permet de garder une séparation entre la logique métier et l'interface utilisateur. + Le concept est simple : chaque partie de l'application a un **rôle bien défini** et ne doit pas empiéter sur le rôle des autres. - Dans la majorité des cas, les middlewares s'exécutent avant le contrôleur même si on peut en avoir à différents moments de la circulation de la donnée. - Si tu as déjà utilisé Express, tu as probablement déjà utilisé un middleware pour vérifier si l'utilisateur est connecté avant de lui afficher une page qui est réservée aux utilisateurs connectés. + Dans la majorité des cas, les middlewares s'exécutent avant le contrôleur même si on peut en avoir à différents + moments de la circulation de la donnée. Si tu as déjà utilisé Express, tu as probablement déjà utilisé un middleware + pour vérifier si l'utilisateur est connecté avant de lui afficher une page qui est réservée aux utilisateurs + connectés. D'après toi, est-ce que React doit être considéré comme la vue dans le design pattern MVC ? La réponse est **non** ! - React est une bibliothèque _(pas une "librarie" et encore moins un framework ⚠️)_ JavaScript qui permet de créer des interfaces utilisateur, mais elle n'est pas liée de manière directe à un serveur. - Certes, on va consommer une API pour récupérer des données, mais React n'est que le réceptacle de ces données côté client _(navigateur)_. +React est une bibliothèque _(pas une "librarie" et encore moins un framework ⚠️)_ JavaScript qui permet de créer des interfaces utilisateur, mais elle n'est pas liée de manière directe à un serveur. + Certes, on va consommer une API pour récupérer des données, mais React n'est que le réceptacle de ces données côté client _(navigateur)_. + +On va donc faire simple : on parlera plutôt d'une architecture "client-serveur" avec React côté client et notre API côté serveur. + Mais ça n'empêche pas que ton API puisse être une API REST _(ou GraphQL)_ qui respecte le design pattern MVC ! + Tout dépendra de si tu demandes dans ton serveur back-end de retourner une vue _(HTML)_ au navigateur. - On va donc faire simple : on parlera plutôt d'une architecture "client-serveur" avec React côté client et notre API côté serveur. - Mais ça n'empêche pas que ton API puisse être une API REST _(ou GraphQL)_ qui respecte le design pattern MVC ! - Tout dépendra de si tu demandes dans ton serveur back-end de retourner une vue _(HTML)_ au navigateur. ## 🧑‍⚖️ Règles et conventions de nommage @@ -73,15 +77,15 @@ Si tu fais un projet personnel, tu peux définir les tiennes, du moment que tu e Pense à être cohérent en ce qui concerne la langue utilisée. - - Évite de mélanger plusieurs langues dans tes nommages. - Si tu choisis de travailler en français, reste en français. - Si tu choisis de travailler en anglais, reste en anglais. - + + Évite de mélanger plusieurs langues dans tes nommages. Si tu choisis de travailler en français, reste en français. Si + tu choisis de travailler en anglais, reste en anglais. + - D'ailleurs, je te recommande chaudement de travailler en anglais ne serait-ce que pour te familiariser avec la langue de Shakespeare qui est, on le rappelle, la langue la plus répandue dans le monde de l'informatique. +D'ailleurs, je te recommande chaudement de travailler en anglais ne serait-ce que pour te familiariser avec la langue de Shakespeare qui est, on le rappelle, la langue la plus répandue dans le monde de l'informatique. + +Tu as évidemment le droit d'utiliser des traducteurs en ligne pour t'aider à trouver le bon mot _(ou la bonne expression)_, on ne te demande pas d'être bilingue ! - Tu as évidemment le droit d'utiliser des traducteurs en ligne pour t'aider à trouver le bon mot _(ou la bonne expression)_, on ne te demande pas d'être bilingue ! Au delà de la langue utilisée, on va également parler de la syntaxe des noms de fichiers, dossiers, classes, méthodes, variables, etc. @@ -117,9 +121,10 @@ Si on prend l'exemple d'un formulaire d'inscription où nous vérifions que l'ut Si je te parle de client HTTP, tu me réponds... ? [Bruno](https://www.usebruno.com/) ? [Postman](https://www.postman.com/) ? [Insomnia](https://insomnia.rest/) ? - Bingo ! 🎉 +Bingo ! 🎉 + +Utiliser un client HTTP comme Bruno, Postman ou Insomnia te permettra de tester facilement les routes de ton API, et de vérifier que les données que tu envoies sont bien traitées par ton serveur. - Utiliser un client HTTP comme Bruno, Postman ou Insomnia te permettra de tester facilement les routes de ton API, et de vérifier que les données que tu envoies sont bien traitées par ton serveur. ### 🧪 Les tests unitaires diff --git a/app/public/images/patterns/mvc.webp b/app/public/images/patterns/mvc.webp new file mode 100644 index 0000000000000000000000000000000000000000..29311f0495ca5a0a111bb37c67f797ab238ff0b0 GIT binary patch literal 14720 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 F{|^_EUvvNf literal 0 HcmV?d00001