From 5241a6b7c16ea3df812fb8c39df9f4cb618391ca Mon Sep 17 00:00:00 2001
From: Maxime Golfier <25312957+maxgfr@users.noreply.github.com>
Date: Fri, 25 Aug 2023 14:56:45 +0200
Subject: [PATCH] feat(ui): replace `theme-ui` by `mui` + migration vers `dsfr`
(#992)
---
.github/workflows/quality.yml | 6 +-
.github/workflows/release.yml | 2 +-
.node-version | 2 +-
targets/frontend/next.config.js | 102 ++---
targets/frontend/package.json | 5 +-
.../__tests__/contenus/contentList.test.tsx | 4 +
.../src/components/alerts/AlertTabs.tsx | 48 ++-
.../src/components/alerts/AlertTitle.tsx | 12 +-
.../frontend/src/components/alerts/Status.tsx | 10 +-
.../src/components/button/CopyButton.js | 11 +-
.../frontend/src/components/button/index.tsx | 365 ++++++------------
.../src/components/changes/ChangeGroup.tsx | 267 ++++++++-----
.../src/components/changes/ViewDiff.js | 13 +-
.../src/components/collapsible/index.js | 2 +-
.../src/components/comments/Comment.js | 17 +-
.../src/components/comments/CommentForm.js | 15 +-
.../src/components/comments/CommentList.js | 7 +-
.../frontend/src/components/comments/index.js | 54 ++-
.../src/components/confirmButton/index.tsx | 53 +--
.../contributions/answers/Answer.tsx | 16 +-
.../contributions/questions/EditQuestion.tsx | 23 +-
.../frontend/src/components/dialog/index.js | 12 +-
.../src/components/documents/Actions.js | 10 +-
.../src/components/documents/Container.js | 17 +-
.../frontend/src/components/documents/List.js | 90 +++--
.../src/components/documents/SearchFilters.js | 159 +++++---
.../editorialContent/ContentSections.tsx | 11 +-
.../editorialContent/EditorialContent.tsx | 11 +-
.../editorialContent/MarkdownPreviewModal.tsx | 9 +-
.../editorialContent/ReferenceBlocks.tsx | 18 +-
.../editorialContent/References.tsx | 11 +-
.../components/editorialContent/Section.tsx | 26 +-
.../editorialContent/SectionBlock.tsx | 5 +-
.../editorialContent/SectionBlocks.tsx | 16 +-
.../src/components/export-es/Status.tsx | 40 +-
.../components/export-es/TriggerButton.tsx | 31 +-
.../src/components/fiches-sp/addFiche.js | 6 +-
.../src/components/fiches-sp/addFicheForm.js | 34 +-
.../components/fiches-sp/fichesSpContainer.js | 4 +-
.../frontend/src/components/fiches-sp/list.js | 122 ------
.../src/components/fiches-sp/list.tsx | 113 ++++++
.../src/components/fiches-sp/selectActions.js | 8 +-
.../forms/ContentPicker/ContentSearch.js | 30 +-
.../forms/ContentPicker/SortableList.js | 48 ++-
.../forms/ContentPicker/ThemePicker.js | 21 +-
.../forms/ContentPicker/ThemeSearch.js | 34 +-
.../src/components/forms/ErrorMessage.js | 7 +-
.../frontend/src/components/forms/Fieldset.js | 9 +-
.../src/components/forms/IconPicker.js | 29 +-
.../src/components/forms/Lister/List.js | 43 ++-
.../src/components/forms/Lister/index.js | 34 +-
.../src/components/glossary/TermForm.js | 48 ++-
.../src/components/glossary/TermList.js | 29 +-
.../src/components/home/DuplicateItems.tsx | 5 +-
.../home/InvisibleLinkedDocument.tsx | 5 +-
.../src/components/home/UnThemedContent.tsx | 7 +-
.../src/components/layout/Container.js | 2 -
.../frontend/src/components/layout/Inline.js | 32 +-
.../src/components/layout/LogoAdmin.tsx | 6 +-
targets/frontend/src/components/layout/Nav.js | 13 +-
.../src/components/layout/NavigationItem.tsx | 11 +-
.../frontend/src/components/layout/Stack.js | 7 +-
.../src/components/layout/UserMenu.tsx | 35 +-
.../src/components/layout/auth.layout.tsx | 7 +-
.../frontend/src/components/layout/header.tsx | 2 -
.../src/components/layout/password.layout.js | 12 +-
.../frontend/src/components/layout/spaces.js | 3 +-
targets/frontend/src/components/list/index.js | 2 +-
.../frontend/src/components/login/index.js | 127 +++---
.../src/components/pagination/index.js | 6 +-
.../components/prequalified/Prequalified.tsx | 18 +-
.../components/prequalified/ValidationBar.tsx | 26 +-
.../src/components/storage/DropZone.js | 15 +-
.../frontend/src/components/table/index.tsx | 36 +-
targets/frontend/src/components/tabs/index.js | 51 ---
.../frontend/src/components/themes/Form.js | 51 ++-
.../frontend/src/components/themes/List.js | 41 +-
targets/frontend/src/components/themes/Map.js | 22 +-
.../src/components/themes/MapModal.js | 25 +-
targets/frontend/src/components/user/List.js | 117 ++----
.../src/components/user/PasswordForm.js | 12 +-
.../frontend/src/components/user/UserForm.js | 43 ++-
.../src/components/utils/BreadcrumbLink.tsx | 25 ++
.../src/components/utils/SimpleLink.tsx | 17 +-
.../frontend/src/components/utils/index.ts | 1 +
targets/frontend/src/pages/_app.js | 32 +-
targets/frontend/src/pages/_document.js | 48 +--
.../src/pages/alerts/[[...params]].tsx | 33 +-
.../frontend/src/pages/change_password.tsx | 4 +-
targets/frontend/src/pages/contenus/[id].tsx | 4 +-
.../pages/contenus/create/[[...source]].tsx | 20 +-
.../create/createContent.mutation.graphql | 17 +-
.../frontend/src/pages/contenus/edit/[id].tsx | 51 +--
.../frontend/src/pages/contenus/edit/utils.ts | 21 +
targets/frontend/src/pages/duplicates.tsx | 14 +-
targets/frontend/src/pages/fichiers.js | 135 ++++---
.../frontend/src/pages/ghost-documents.tsx | 12 +-
.../src/pages/glossary/edit/[[...id]].js | 15 +-
targets/frontend/src/pages/glossary/index.js | 60 ++-
targets/frontend/src/pages/index.tsx | 10 +-
targets/frontend/src/pages/kali/blocks.js | 57 ++-
targets/frontend/src/pages/login.js | 11 +-
targets/frontend/src/pages/mises-a-jour.tsx | 34 +-
targets/frontend/src/pages/reset_password.js | 14 +-
.../frontend/src/pages/themes/[[...id]].js | 75 ++--
.../frontend/src/pages/themes/[id]/create.js | 2 +-
.../frontend/src/pages/themes/edit/[id].js | 14 +-
targets/frontend/src/pages/unthemed.js | 88 +++--
targets/frontend/src/pages/user/account.js | 60 +--
targets/frontend/src/pages/user/edit/[id].js | 3 -
targets/frontend/src/pages/user/new.js | 6 +-
targets/frontend/src/pages/users.js | 12 +-
targets/frontend/src/theme.ts | 2 +-
yarn.lock | 218 +++++------
114 files changed, 2020 insertions(+), 1953 deletions(-)
delete mode 100644 targets/frontend/src/components/fiches-sp/list.js
create mode 100644 targets/frontend/src/components/fiches-sp/list.tsx
delete mode 100644 targets/frontend/src/components/tabs/index.js
create mode 100644 targets/frontend/src/components/utils/BreadcrumbLink.tsx
create mode 100644 targets/frontend/src/pages/contenus/edit/utils.ts
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
index 81a1c03a9..a17247f95 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -20,7 +20,7 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v3
with:
- node-version: 20
+ node-version: 20.3.1
cache: "yarn"
- name: Install dependencies
run: |
@@ -61,7 +61,7 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v3
with:
- node-version: 20
+ node-version: 20.3.1
cache: "yarn"
- name: Lint ${{ matrix.repositories }}
run: |
@@ -94,7 +94,7 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v3
with:
- node-version: 20
+ node-version: 20.3.1
cache: "yarn"
- name: Test ${{ matrix.repositories }}
run: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fb2f18e94..fede5954d 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -20,7 +20,7 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v3
with:
- node-version: 20
+ node-version: 20.3.1
cache: "yarn"
- name: Install dependencies
run: yarn install --frozen-lockfile
diff --git a/.node-version b/.node-version
index 209e3ef4b..2edeafb09 100644
--- a/.node-version
+++ b/.node-version
@@ -1 +1 @@
-20
+20
\ No newline at end of file
diff --git a/targets/frontend/next.config.js b/targets/frontend/next.config.js
index 5a8f1a335..756410947 100644
--- a/targets/frontend/next.config.js
+++ b/targets/frontend/next.config.js
@@ -5,6 +5,7 @@ const withTM = require("next-transpile-modules")([
"@shared/graphql-client",
"@shared/id-generator",
"@socialgouv/cdtn-ui",
+ "@codegouvfr/react-dsfr",
]);
const basePath = "";
@@ -14,54 +15,57 @@ const securityHeaders = [
key: "X-Frame-Options",
value: "deny",
},
- {key: "X-XSS-Protection", value: "1; mode=block"},
- {key: "X-Content-Type-Options", value: "nosniff"},
+ { key: "X-XSS-Protection", value: "1; mode=block" },
+ { key: "X-Content-Type-Options", value: "nosniff" },
];
-module.exports =
- withTM(
- withSourceMaps({
- basePath,
- async headers() {
- return [
- {
- headers: securityHeaders,
- // Apply these headers to all routes in your application.
- source: "/:path*",
- },
- ];
- },
- poweredByHeader: false,
- serverRuntimeConfig: {
- rootDir: __dirname,
- },
- webpack: (config, {isServer, dev}) => {
- config.output.chunkFilename = isServer
- ? `${dev ? "[name]" : "[name].[fullhash]"}.js`
- : `static/chunks/${dev ? "[name]" : "[name].[fullhash]"}.js`;
- config.module.rules.push({
- exclude: /node_modules/,
- loader: "graphql-tag/loader",
- test: /\.(graphql|gql)$/,
- });
- // In `pages/_app.js`, Sentry is imported from @sentry/node. While
- // @sentry/browser will run in a Node.js environment, @sentry/node will use
- // Node.js-only APIs to catch even more unhandled exceptions.
- //
- // This works well when Next.js is SSRing your page on a server with
- // Node.js, but it is not what we want when your client-side bundle is being
- // executed by a browser.
- //
- // Luckily, Next.js will call this webpack function twice, once for the
- // server and once for the client. Read more:
- // https://nextjs.org/docs#customizing-webpack-config
- //
- // So ask Webpack to replace @sentry/node imports with @sentry/browser when
- // building the browser's bundle
- if (!isServer) {
- config.resolve.alias["@sentry/node"] = "@sentry/browser";
- }
- return config;
- },
- })
- );
+module.exports = withTM(
+ withSourceMaps({
+ basePath,
+ async headers() {
+ return [
+ {
+ headers: securityHeaders,
+ // Apply these headers to all routes in your application.
+ source: "/:path*",
+ },
+ ];
+ },
+ poweredByHeader: false,
+ serverRuntimeConfig: {
+ rootDir: __dirname,
+ },
+ webpack: (config, { isServer, dev }) => {
+ config.output.chunkFilename = isServer
+ ? `${dev ? "[name]" : "[name].[fullhash]"}.js`
+ : `static/chunks/${dev ? "[name]" : "[name].[fullhash]"}.js`;
+ config.module.rules.push({
+ exclude: /node_modules/,
+ loader: "graphql-tag/loader",
+ test: /\.(graphql|gql)$/,
+ });
+ // In `pages/_app.js`, Sentry is imported from @sentry/node. While
+ // @sentry/browser will run in a Node.js environment, @sentry/node will use
+ // Node.js-only APIs to catch even more unhandled exceptions.
+ //
+ // This works well when Next.js is SSRing your page on a server with
+ // Node.js, but it is not what we want when your client-side bundle is being
+ // executed by a browser.
+ //
+ // Luckily, Next.js will call this webpack function twice, once for the
+ // server and once for the client. Read more:
+ // https://nextjs.org/docs#customizing-webpack-config
+ //
+ // So ask Webpack to replace @sentry/node imports with @sentry/browser when
+ // building the browser's bundle
+ if (!isServer) {
+ config.resolve.alias["@sentry/node"] = "@sentry/browser";
+ }
+ config.module.rules.push({
+ test: /\.woff2$/,
+ type: "asset/resource",
+ });
+ return config;
+ },
+ })
+);
diff --git a/targets/frontend/package.json b/targets/frontend/package.json
index 9ce8a0855..980e0b5cc 100644
--- a/targets/frontend/package.json
+++ b/targets/frontend/package.json
@@ -4,8 +4,10 @@
"dependencies": {
"@azure/abort-controller": "^1.0.4",
"@azure/storage-blob": "^12.7.0",
+ "@codegouvfr/react-dsfr": "^0.74.2",
"@elastic/elasticsearch": "^7.14.1",
"@emotion/react": "11.10.6",
+ "@emotion/server": "^11.11.0",
"@emotion/styled": "11.10.6",
"@hapi/boom": "^9.1.4",
"@hapi/joi": "^17.1.1",
@@ -74,7 +76,6 @@
"strip-markdown": "^4.2.0",
"styled-components": "^5.3.9",
"swr": "^1.0.1",
- "theme-ui": "^0.11.2",
"unified": "^9.2.2",
"unist-util-parents": "^1.0.3",
"unist-util-select": "^4.0.1",
@@ -117,6 +118,8 @@
"lint": "next lint",
"precommit": "lint-staged",
"start": "next start",
+ "predev": "only-include-used-icons",
+ "prebuild": "only-include-used-icons",
"prepush": "yarn build && yarn lint && yarn test --bail --changedSince=master",
"test": "jest"
}
diff --git a/targets/frontend/src/__tests__/contenus/contentList.test.tsx b/targets/frontend/src/__tests__/contenus/contentList.test.tsx
index 7e5b8b295..906fc9d82 100644
--- a/targets/frontend/src/__tests__/contenus/contentList.test.tsx
+++ b/targets/frontend/src/__tests__/contenus/contentList.test.tsx
@@ -9,6 +9,10 @@ jest.mock("next/router", () => ({
}),
}));
+jest.mock("@codegouvfr/react-dsfr/useIsDark", () => ({
+ useIsDark: jest.fn().mockReturnValue(false),
+}));
+
describe("Given parameters", () => {
describe("When rendering the component DocumentsPage", () => {
let rendering: RenderResult;
diff --git a/targets/frontend/src/components/alerts/AlertTabs.tsx b/targets/frontend/src/components/alerts/AlertTabs.tsx
index 4719531c2..d48643da9 100644
--- a/targets/frontend/src/components/alerts/AlertTabs.tsx
+++ b/targets/frontend/src/components/alerts/AlertTabs.tsx
@@ -1,12 +1,13 @@
import Link from "next/link";
import PropTypes from "prop-types";
import { getStatusLabel, slugifyRepository } from "src/models";
-import { Spinner } from "theme-ui";
+import CircularProgress from "@mui/material/CircularProgress";
import { useQuery } from "urql";
+import { Tabs, Tab } from "@mui/material";
-import { TabItem, Tabs } from "../tabs";
import { FixedSnackBar } from "../utils/SnackBar";
import React from "react";
+import { useRouter } from "next/router";
const countAlertByStatusQuery = `
query getAlerts($repository: String!) {
@@ -30,6 +31,14 @@ export function AlertTabs({
repository: string;
activeStatus: string;
}) {
+ const router = useRouter();
+
+ const [value, setValue] = React.useState(0);
+
+ const handleChange = (event: React.SyntheticEvent, newValue: number) => {
+ setValue(newValue);
+ };
+
const [result] = useQuery({
query: countAlertByStatusQuery,
variables: {
@@ -37,10 +46,19 @@ export function AlertTabs({
},
});
+ React.useEffect(() => {
+ const status = result.data?.statuses.find(
+ (status: any) => status.name === activeStatus
+ );
+ if (status) {
+ setValue(result.data?.statuses.indexOf(status));
+ }
+ }, [result.data, activeStatus]);
+
const { fetching, error, data } = result;
if (fetching) {
- return ;
+ return ;
}
if (error) {
@@ -52,19 +70,21 @@ export function AlertTabs({
}
return (
-
+
{data.statuses.map((status: any) => (
-
-
- {getStatusLabel(status.name)} ({status.alerts.aggregate.count})
-
-
+ label={`${getStatusLabel(status.name)} (${
+ status.alerts.aggregate.count
+ })`}
+ onClick={() => {
+ router.push(
+ `/alerts/${slugifyRepository(repository)}/${status.name}`,
+ undefined,
+ { shallow: true }
+ );
+ }}
+ />
))}
);
diff --git a/targets/frontend/src/components/alerts/AlertTitle.tsx b/targets/frontend/src/components/alerts/AlertTitle.tsx
index 6f3cdceda..a319480d7 100644
--- a/targets/frontend/src/components/alerts/AlertTitle.tsx
+++ b/targets/frontend/src/components/alerts/AlertTitle.tsx
@@ -17,15 +17,15 @@ export const AlertTitle: React.FC = ({ alertId, info, children }) => {
return (
- {children}
+ {children}
{info.type === "dila" && info.num && (
-
+
= ({ alertId, info, children }) => {
setShowComment(!showComment)}
>
-
+
{showComment && }
diff --git a/targets/frontend/src/components/alerts/Status.tsx b/targets/frontend/src/components/alerts/Status.tsx
index 3b7dc6e8c..d02c758ac 100644
--- a/targets/frontend/src/components/alerts/Status.tsx
+++ b/targets/frontend/src/components/alerts/Status.tsx
@@ -25,16 +25,16 @@ export function AlertStatus({ alertId }: { alertId: string }) {
}
return (
-
-
-
@@ -75,7 +75,7 @@ function Recap({ publications }) {
);
return (
- Détails
+ Détails
{items.published > 0 && (
-
diff --git a/targets/frontend/src/components/documents/Container.js b/targets/frontend/src/components/documents/Container.js
index 477bfb767..23470e40c 100644
--- a/targets/frontend/src/components/documents/Container.js
+++ b/targets/frontend/src/components/documents/Container.js
@@ -5,7 +5,7 @@ import PropTypes from "prop-types";
import { useCallback, useMemo } from "react";
import { IoMdAdd } from "react-icons/io";
import { useSelectionContext } from "src/pages/contenus";
-import { Card, Flex, Message } from "theme-ui";
+import { Card, Alert, Box } from "@mui/material";
import { useMutation, useQuery } from "urql";
import { Stack } from "../layout/Stack";
@@ -13,6 +13,7 @@ import { Pagination } from "../pagination";
import { DocumentsListActions } from "./Actions";
import { DocumentList } from "./List";
import { SearchFilters } from "./SearchFilters";
+import { theme } from "src/theme";
export function DocumentListContainer({ initialFilterValues }) {
const router = useRouter();
@@ -67,11 +68,11 @@ export function DocumentListContainer({ initialFilterValues }) {
const { fetching, error, data } = result;
if (error) {
- return {error.message};
+ return {error.message};
}
return (
-
+
Ajouter un contenu
-
-
+
+
-
-
- |
- Document |
- Publié |
- Disponible |
-
-
-
+
+
+
+
+ Document
+ Publié
+ Disponible
+
+
+
{documents.map((doc) => (
))}
-
-
+
+
);
}
DocumentList.propTypes = {
@@ -54,20 +59,28 @@ const DocumentRow = function DocumentRow({
};
return (
-
-
-
- |
-
+
+
+
+
+
- |
-
+
+
{isPublished ? (
@@ -94,8 +107,8 @@ const DocumentRow = function DocumentRow({
)}
- |
-
+
+
{isAvailable ? (
@@ -105,8 +118,8 @@ const DocumentRow = function DocumentRow({
)}
- |
-
+
+
);
};
@@ -132,10 +145,3 @@ export const sourceToRoute = ({ cdtnId, source }) => {
return `/contenus/${cdtnId}`;
}
};
-
-const checkboxStyles = {
- cursor: "pointer",
- display: "block",
- m: "0 0 0 small",
- padding: 0,
-};
diff --git a/targets/frontend/src/components/documents/SearchFilters.js b/targets/frontend/src/components/documents/SearchFilters.js
index 996aad215..c0feaf713 100644
--- a/targets/frontend/src/components/documents/SearchFilters.js
+++ b/targets/frontend/src/components/documents/SearchFilters.js
@@ -2,7 +2,15 @@ import { getLabelBySource, SOURCES } from "@socialgouv/cdtn-sources";
import PropTypes from "prop-types";
import { useForm } from "react-hook-form";
import { IoMdSearch } from "react-icons/io";
-import { Box, Input, Label, Radio, Select } from "theme-ui";
+import {
+ Box,
+ Input,
+ Select,
+ Radio,
+ FormControlLabel,
+ FormLabel,
+ MenuItem,
+} from "@mui/material";
import { useQuery } from "urql";
import { Button } from "../button";
@@ -59,7 +67,8 @@ export function SearchFilters({ initialValues, onSearchUpdate }) {
console.log("update filters");
onSearchUpdate({
...initialValues,
- [event.target.name]: event.target.value,
+ [event.target.name]:
+ event.target.value === "no-filter" ? "" : event.target.value,
});
}
@@ -69,36 +78,37 @@ export function SearchFilters({ initialValues, onSearchUpdate }) {
return (