Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(contributions): ajouter des infographies #1544

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 185 additions & 2 deletions targets/frontend/src/components/forms/EditionField/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,18 @@ import { DetailsSummary } from "@tiptap-pro/extension-details-summary";
import { DetailsContent } from "@tiptap-pro/extension-details-content";
import { Placeholder } from "@tiptap/extension-placeholder";
import { Link } from "@tiptap/extension-link";
import { Alert, Title } from "./extensions";
import { Alert, Infographic, Title } from "./extensions";
import { MenuInfographic } from "./MenuInfographic";
import {
Button,
DialogActions,
DialogContentText,
TextField,
} from "@mui/material";
import DialogTitle from "@mui/material/DialogTitle";
import Dialog from "@mui/material/Dialog";
import DialogContent from "@mui/material/DialogContent";
import { NodeSelection } from "@tiptap/pm/state";

export type EditorProps = {
label: string;
Expand All @@ -29,6 +40,35 @@ export type EditorProps = {

const emptyHtml = "<p></p>";

type ModeCreation = {
mode: 0;
};
const Creation: ModeCreation = { mode: 0 };

type ModeEdition = {
mode: 1;
infoUrl: string;
pdfUrl: string;
pdfSize: string;
};
const Edition = (
infoUrl: string,
pdfUrl: string,
pdfSize: string
): ModeEdition => ({
mode: 1,
infoUrl,
pdfUrl,
pdfSize,
});

type ModeHide = {
mode: -1;
};
const Hide: ModeHide = { mode: -1 };

type Mode = ModeEdition | ModeCreation | ModeHide;

export const Editor = ({
label,
content,
Expand All @@ -39,6 +79,8 @@ export const Editor = ({
const [currentContent, setCurrentContent] = useState(content);
const [focus, setFocus] = useState(false);
const [isClient, setIsClient] = useState(false);
const [infographicModal, setInfographicModal] = useState<Mode>(Hide);

const editor = useEditor({
content,
editable: !disabled,
Expand Down Expand Up @@ -75,6 +117,7 @@ export const Editor = ({
}),
Alert,
Title,
Infographic,
],
onUpdate: ({ editor }) => {
const html = editor.getHTML();
Expand All @@ -98,6 +141,36 @@ export const Editor = ({
editor?.setOptions({ editable: !disabled });
}, [disabled]);

useEffect(() => {
// We need to focus on the infographic to edit it
const handleClick = (event: MouseEvent) => {
const target = event.target as HTMLElement;

if (
target.tagName === "IMG" &&
target.closest(".infographic") &&
editor
) {
const pos = editor.view.posAtDOM(
target.closest(".infographic") as HTMLElement,
0
);

editor.view.dispatch(
editor.state.tr.setSelection(
NodeSelection.create(editor.state.doc, pos)
)
);
editor.commands.focus();
}
};

document.addEventListener("click", handleClick);
return () => {
document.removeEventListener("click", handleClick);
};
}, [editor]);

return (
<>
{isClient && (
Expand All @@ -109,8 +182,28 @@ export const Editor = ({
htmlFor={label}
>
<MenuStyle editor={editor} />
<MenuSpecial editor={editor} />
<MenuSpecial
editor={editor}
onNewInfographic={() => {
setInfographicModal(Creation);
}}
/>
<MenuTable editor={editor} />
<MenuInfographic
editor={editor}
onEdit={() => {
const node = editor?.state.selection.$from.node();
if (node?.type.name === "infographic") {
const src = node.attrs.src;
const dataPdf = node.attrs.urlPdf;
const dataPdfSize = node.attrs.pdfSize;
setInfographicModal(Edition(src, dataPdf, dataPdfSize));
}
}}
onDelete={() => {
editor?.commands.removeInfographic();
}}
/>

<StyledEditorContent
editor={editor}
Expand All @@ -126,6 +219,92 @@ export const Editor = ({
/>
</TitleBox>
)}
<Dialog
open={infographicModal.mode !== Hide.mode}
onClose={() => {
setInfographicModal(Hide);
}}
PaperProps={{
component: "form",
onSubmit: (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const { infoUrl, pdfUrl, pdfSize } = Object.fromEntries(
(formData as any).entries()
);
if (infographicModal.mode === Creation.mode) {
editor
?.chain()
.focus()
.setInfographic(infoUrl, pdfUrl, pdfSize)
.run();
} else {
editor?.commands.updateInfographicSrc(infoUrl, pdfUrl, pdfSize);
}
setInfographicModal(Hide);
},
}}
>
<DialogTitle>Infographie</DialogTitle>
<DialogContent>
<DialogContentText>
Veuillez renseigner les informations suivantes pour ajouter une
infographie au document
</DialogContentText>
<TextField
autoFocus
required
margin="dense"
id="infoUrl"
name="infoUrl"
label="URL vers l'infographie"
defaultValue={
infographicModal.mode === 1 ? infographicModal.infoUrl : undefined
}
type="text"
fullWidth
variant="standard"
/>
<TextField
required
margin="dense"
id="pdfUrl"
name="pdfUrl"
label="URL vers le PDF"
defaultValue={
infographicModal.mode === 1 ? infographicModal.pdfUrl : undefined
}
type="text"
fullWidth
variant="standard"
/>
<TextField
required
margin="dense"
id="pdfSize"
name="pdfSize"
label="Taille du PDF"
defaultValue={
infographicModal.mode === 1 ? infographicModal.pdfSize : undefined
}
type="text"
fullWidth
variant="standard"
/>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
setInfographicModal(Hide);
}}
>
Annuler
</Button>
<Button type="submit">
{infographicModal.mode === Creation.mode ? "Ajouter" : "Modifier"}
</Button>
</DialogActions>
</Dialog>
</>
);
};
Expand Down Expand Up @@ -170,6 +349,10 @@ const StyledEditorContent = styled(EditorContent)(() => {
backgroundColor: fr.colors.decisions.background.contrast.info.active,
borderRadius: "0.6rem",
},
".infographic": {
marginBottom: "1.6rem",
color: fr.colors.decisions.text.default,
},
li: {
p: {
margin: "0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Editor, FloatingMenu } from "@tiptap/react";
import Delete from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import { styled } from "@mui/system";

export const MenuInfographic = ({
editor,
onEdit,
onDelete,
}: {
editor: Editor | null;
onEdit: () => void;
onDelete: () => void;
}) => {
return editor ? (
<InfographicFloatingMenu
className="floating-menu"
tippyOptions={{ duration: 100, maxWidth: 500 }}
editor={editor}
shouldShow={({ editor, state }) => {
return (
editor?.state.selection.$from.node()?.type.name === "infographic" &&
state.selection.content().content.size > 0 &&
editor.isActive("infographic")
);
}}
>
<button onClick={onEdit} type="button" title="Editer l'infographie">
<EditIcon width={24} fill="white" />
</button>
<button onClick={onDelete} type="button" title="Supprimer l'infographie">
<Delete />
</button>
</InfographicFloatingMenu>
) : (
<></>
);
};

const InfographicFloatingMenu = styled(FloatingMenu)`
display: flex;
background-color: #0d0d0d;
padding: 0.2rem;
border-radius: 0.5rem;

button {
border: none;
background: none;
font-size: 0.85rem;
font-weight: 500;
padding: 0 0.2rem;
opacity: 0.6;
color: #fff;

&:hover,
&.is-active {
opacity: 1;
}
}
`;
18 changes: 12 additions & 6 deletions targets/frontend/src/components/forms/EditionField/MenuSpecial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import {
} from "@tiptap/react";
import FormatListBulletedIcon from "@mui/icons-material/FormatListBulleted";
import FormatListNumberedIcon from "@mui/icons-material/FormatListNumbered";
import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
import GridOnIcon from "@mui/icons-material/GridOn";
import StorageIcon from "@mui/icons-material/Storage";
import { styled } from "@mui/system";
import InfoIcon from "@mui/icons-material/Info";
import { Node as ProseMirrorNode } from "@tiptap/pm/model";

const tableHTML = `
Expand All @@ -25,7 +25,13 @@ const tableHTML = `
</table>
`;

export const MenuSpecial = ({ editor }: { editor: Editor | null }) => {
export const MenuSpecial = ({
editor,
onNewInfographic,
}: {
editor: Editor | null;
onNewInfographic: (editor: Editor) => void;
}) => {
const getTextContent = (node: ProseMirrorNode) => {
if (editor) {
return getText(node, {
Expand Down Expand Up @@ -110,13 +116,13 @@ export const MenuSpecial = ({ editor }: { editor: Editor | null }) => {
</button>
<button
onClick={() => {
editor?.chain().focus().setAlert().run();
onNewInfographic(editor);
}}
className={editor.isActive("alert") ? "is-active" : ""}
className={editor.isActive("infographic") ? "is-active" : ""}
type="button"
title="Section d'alerte"
title="Infographie"
>
<InfoIcon />
<AddPhotoAlternateIcon />
</button>
</StyledFloatingMenu>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const Alert = Node.create<AlertOptions>({
group: "block",

parseHTML() {
return [{ tag: "div" }];
return [{ tag: "div.alert" }];
},

renderHTML({ HTMLAttributes }) {
Expand Down
Loading
Loading