Skip to content

Commit

Permalink
✨(frontend) Added copy-as buttons for HTML and Markdown
Browse files Browse the repository at this point in the history
Added buttons to the Document Toolbox to copy the content of the currently open editor to the clipboard, either as HTML or as Markdown. Closes suitenumerique#300
  • Loading branch information
rvveber committed Oct 15, 2024
1 parent 97d00b6 commit 6cfa8cd
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { Button } from '@openfun/cunningham-react';
import {
Button,
VariantType,
useToastProvider,
} from '@openfun/cunningham-react';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';

import { Box, DropButton, IconOptions } from '@/components';
import { useAuthStore } from '@/core';
import { usePanelEditorStore } from '@/features/docs/doc-editor/';
import { useDocStore, usePanelEditorStore } from '@/features/docs/doc-editor/';
import {
Doc,
ModalRemoveDoc,
Expand All @@ -31,6 +35,24 @@ export const DocToolBox = ({ doc, versionId }: DocToolBoxProps) => {
const [isModalVersionOpen, setIsModalVersionOpen] = useState(false);
const { isSmallMobile } = useResponsiveStore();
const { authenticated } = useAuthStore();
const { docsStore } = useDocStore();
const { toast } = useToastProvider();

const getDocContentFormatted = (
format: 'html' | 'markdown',
): Promise<string> => {
const editor = docsStore[doc.id]?.editor;
if (!editor) {
return Promise.reject(new Error('Editor not available'));
}

switch (format) {
case 'html':
return editor.blocksToHTMLLossy();
case 'markdown':
return editor.blocksToMarkdownLossy();
}
};

return (
<Box
Expand Down Expand Up @@ -125,6 +147,78 @@ export const DocToolBox = ({ doc, versionId }: DocToolBoxProps) => {
{t('Delete document')}
</Button>
)}
<Button
onClick={() => {
setIsDropOpen(false);
getDocContentFormatted('markdown').then(
(docContentFormatted) => {
navigator.clipboard.writeText(docContentFormatted).then(
() =>
toast(t('Copied to clipboard'), VariantType.SUCCESS, {
duration: 3000,
}),
() =>
toast(
t('Failed to copy to clipboard'),
VariantType.ERROR,
{ duration: 3000 },
),
);
},
() =>
toast(
t('Editor') + ' ' + t('unavailable'),
VariantType.ERROR,
{
duration: 3000,
},
),
);
}}
color="primary-text"
icon={<span className="material-icons">content_copy</span>}
size="small"
>
<Text $theme="primary">
{t('Copy as {{subject}}', { subject: 'Markdown' })}
</Text>
</Button>
<Button
onClick={() => {
setIsDropOpen(false);
getDocContentFormatted('html').then(
(docContentFormatted) => {
navigator.clipboard.writeText(docContentFormatted).then(
() =>
toast(t('Copied to clipboard'), VariantType.SUCCESS, {
duration: 3000,
}),
() =>
toast(
t('Failed to copy to clipboard'),
VariantType.ERROR,
{ duration: 3000 },
),
);
},
() =>
toast(
t('Editor') + ' ' + t('unavailable'),
VariantType.ERROR,
{
duration: 3000,
},
),
);
}}
color="primary-text"
icon={<span className="material-icons">content_copy</span>}
size="small"
>
<Text $theme="primary">
{t('Copy as {{subject}}', { subject: 'HTML' })}
</Text>
</Button>
</Box>
</DropButton>
</Box>
Expand Down
4 changes: 4 additions & 0 deletions src/frontend/apps/impress/src/i18n/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"Content modal to export the document": "Contenu modal pour exporter le document",
"Cookies placed": "Cookies déposés",
"Copy link": "Copier le lien",
"Copy as {{subject}}": "Copier en {{subject}}",
"Copied to clipboard": "Copié dans le presse-papiers",
"Copyright": "Copyright",
"Create a new document": "Créer un nouveau document",
"Created at": "Créé le",
Expand Down Expand Up @@ -49,6 +51,7 @@
"Export your document, it will be inserted in the selected template.": "Exportez votre document, il sera inséré dans le modèle sélectionné.",
"Failed to add the member in the document.": "Impossible d'ajouter le membre dans le document.",
"Failed to copy link": "Échec de la copie du lien",
"Failed to copy to clipboard": "Échec de la copie dans le presse-papiers",
"Failed to create the invitation for {{email}}.": "Impossible de créer l'invitation pour {{email}}.",
"Find a member to add to the document": "Trouver un membre à ajouter au document",
"French Interministerial Directorate for Digital Affairs (DINUM), 20 avenue de Ségur 75007 Paris.": "Direction interministérielle des affaires numériques (DINUM), 20 avenue de Segur 75007 Paris.",
Expand Down Expand Up @@ -142,6 +145,7 @@
"Your role": "Votre rôle",
"Your role:": "Votre rôle:",
"Your {{format}} was downloaded succesfully": "Votre {{format}} a été téléchargé avec succès",
"unavailable": "indisponible",
"accessibility-contact-defenseurdesdroits": "Contacter le délégué du<1>Défenseur des droits dans votre région</1>",
"accessibility-dinum-services": "<strong>DINUM</strong> s'engage à rendre accessibles ses services numériques, conformément à l'article 47 de la loi n° 2005-102 du 11 février 2005.",
"accessibility-form-defenseurdesdroits": "Écrire un message au<1>Défenseur des droits</1>",
Expand Down

0 comments on commit 6cfa8cd

Please sign in to comment.