♻️(frontend) Simplify AGPL export pattern
We were maintaining two separate components for AGPL and MIT license exports. This commit consolidates the functionality into a single component that handles both licenses, simplifying the codebase and reducing duplication.
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
const originalEnv = process.env.NEXT_PUBLIC_PUBLISH_AS_MIT;
|
||||||
|
|
||||||
|
jest.mock('@/features/docs/doc-export/utils', () => ({
|
||||||
|
anything: true,
|
||||||
|
}));
|
||||||
|
jest.mock('@/features/docs/doc-export/components/ModalExport', () => ({
|
||||||
|
ModalExport: () => <span>ModalExport</span>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('useModuleExport', () => {
|
||||||
|
afterAll(() => {
|
||||||
|
process.env.NEXT_PUBLIC_PUBLISH_AS_MIT = originalEnv;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
jest.resetModules();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return undefined when NEXT_PUBLIC_PUBLISH_AS_MIT is true', async () => {
|
||||||
|
process.env.NEXT_PUBLIC_PUBLISH_AS_MIT = 'true';
|
||||||
|
const Export = await import('@/features/docs/doc-export/');
|
||||||
|
|
||||||
|
expect(Export.default).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load modules when NEXT_PUBLIC_PUBLISH_AS_MIT is false', async () => {
|
||||||
|
process.env.NEXT_PUBLIC_PUBLISH_AS_MIT = 'false';
|
||||||
|
const Export = await import('@/features/docs/doc-export/');
|
||||||
|
|
||||||
|
expect(Export.default).toHaveProperty('ModalExport');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* To import Export modules you must import from the index file.
|
||||||
|
* This is to ensure that the Export modules are only loaded when
|
||||||
|
* the application is not published as MIT.
|
||||||
|
*/
|
||||||
export * from './api';
|
export * from './api';
|
||||||
export * from './components';
|
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
|
|
||||||
|
import * as ModalExport from './components/ModalExport';
|
||||||
|
|
||||||
|
let modulesExport = undefined;
|
||||||
|
if (process.env.NEXT_PUBLIC_PUBLISH_AS_MIT === 'false') {
|
||||||
|
modulesExport = {
|
||||||
|
...ModalExport,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type ModulesExport = typeof modulesExport;
|
||||||
|
|
||||||
|
export default modulesExport as ModulesExport;
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { AppWrapper } from '@/tests/utils';
|
|
||||||
|
|
||||||
import { DocToolBox } from '../components/DocToolBox';
|
|
||||||
|
|
||||||
const doc = {
|
|
||||||
nb_accesses: 1,
|
|
||||||
abilities: {
|
|
||||||
versions_list: true,
|
|
||||||
destroy: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
jest.mock('@/features/docs/doc-export/', () => ({
|
|
||||||
ModalExport: () => <span>ModalExport</span>,
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('DocToolBox dynamic import: loads DocToolBox when NEXT_PUBLIC_PUBLISH_AS_MIT is false', async () => {
|
|
||||||
process.env.NEXT_PUBLIC_PUBLISH_AS_MIT = 'false';
|
|
||||||
|
|
||||||
render(<DocToolBox doc={doc as any} />, {
|
|
||||||
wrapper: AppWrapper,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(await screen.findByText('download')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import { render, screen, waitFor } from '@testing-library/react';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { AppWrapper } from '@/tests/utils';
|
|
||||||
|
|
||||||
const doc = {
|
|
||||||
nb_accesses: 1,
|
|
||||||
abilities: {
|
|
||||||
versions_list: true,
|
|
||||||
destroy: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
jest.mock('@/features/docs/doc-export/', () => ({
|
|
||||||
ModalExport: () => <span>ModalExport</span>,
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('DocToolBox dynamic import: loads DocToolBox when NEXT_PUBLIC_PUBLISH_AS_MIT is true', async () => {
|
|
||||||
process.env.NEXT_PUBLIC_PUBLISH_AS_MIT = 'true';
|
|
||||||
|
|
||||||
const { DocToolBox } = await import('../components/DocToolBox');
|
|
||||||
|
|
||||||
render(<DocToolBox doc={doc as any} />, {
|
|
||||||
wrapper: AppWrapper,
|
|
||||||
});
|
|
||||||
|
|
||||||
await waitFor(
|
|
||||||
() => {
|
|
||||||
expect(screen.queryByText('download')).not.toBeInTheDocument();
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timeout: 1000,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
@@ -1,47 +1,146 @@
|
|||||||
import { Button, useModal } from '@openfun/cunningham-react';
|
import { Button, useModal } from '@openfun/cunningham-react';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import dynamic from 'next/dynamic';
|
import { useEffect, useState } from 'react';
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { css } from 'styled-components';
|
import { css } from 'styled-components';
|
||||||
|
|
||||||
import { Box, Icon } from '@/components';
|
import {
|
||||||
|
Box,
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuOption,
|
||||||
|
Icon,
|
||||||
|
IconOptions,
|
||||||
|
} from '@/components';
|
||||||
import { useCunninghamTheme } from '@/cunningham';
|
import { useCunninghamTheme } from '@/cunningham';
|
||||||
import { Doc } from '@/docs/doc-management';
|
import Export from '@/docs/doc-export/';
|
||||||
import { KEY_LIST_DOC_VERSIONS } from '@/docs/doc-versioning';
|
import {
|
||||||
|
Doc,
|
||||||
|
KEY_DOC,
|
||||||
|
KEY_LIST_DOC,
|
||||||
|
ModalRemoveDoc,
|
||||||
|
useCopyDocLink,
|
||||||
|
useCreateFavoriteDoc,
|
||||||
|
useDeleteFavoriteDoc,
|
||||||
|
} from '@/docs/doc-management';
|
||||||
|
import { DocShareModal } from '@/docs/doc-share';
|
||||||
|
import {
|
||||||
|
KEY_LIST_DOC_VERSIONS,
|
||||||
|
ModalSelectVersion,
|
||||||
|
} from '@/docs/doc-versioning';
|
||||||
|
import { useAnalytics } from '@/libs';
|
||||||
import { useResponsiveStore } from '@/stores';
|
import { useResponsiveStore } from '@/stores';
|
||||||
|
|
||||||
|
import { useCopyCurrentEditorToClipboard } from '../hooks/useCopyCurrentEditorToClipboard';
|
||||||
|
|
||||||
|
const ModalExport = Export?.ModalExport;
|
||||||
|
|
||||||
interface DocToolBoxProps {
|
interface DocToolBoxProps {
|
||||||
doc: Doc;
|
doc: Doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DocToolBoxLicence = dynamic(() =>
|
|
||||||
process.env.NEXT_PUBLIC_PUBLISH_AS_MIT === 'false'
|
|
||||||
? import('./DocToolBoxLicenceAGPL').then((mod) => mod.DocToolBoxLicenceAGPL)
|
|
||||||
: import('./DocToolBoxLicenceMIT').then((mod) => mod.DocToolBoxLicenceMIT),
|
|
||||||
);
|
|
||||||
|
|
||||||
export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const hasAccesses = doc.nb_accesses_direct > 1 && doc.abilities.accesses_view;
|
const hasAccesses = doc.nb_accesses_direct > 1 && doc.abilities.accesses_view;
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const { spacingsTokens } = useCunninghamTheme();
|
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
|
||||||
|
|
||||||
const modalHistory = useModal();
|
const [isModalRemoveOpen, setIsModalRemoveOpen] = useState(false);
|
||||||
|
const [isModalExportOpen, setIsModalExportOpen] = useState(false);
|
||||||
|
const selectHistoryModal = useModal();
|
||||||
const modalShare = useModal();
|
const modalShare = useModal();
|
||||||
|
|
||||||
const { isSmallMobile } = useResponsiveStore();
|
const { isSmallMobile, isDesktop } = useResponsiveStore();
|
||||||
|
const copyDocLink = useCopyDocLink(doc.id);
|
||||||
|
const { isFeatureFlagActivated } = useAnalytics();
|
||||||
|
const removeFavoriteDoc = useDeleteFavoriteDoc({
|
||||||
|
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
||||||
|
});
|
||||||
|
const makeFavoriteDoc = useCreateFavoriteDoc({
|
||||||
|
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (modalHistory.isOpen) {
|
if (selectHistoryModal.isOpen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void queryClient.resetQueries({
|
void queryClient.resetQueries({
|
||||||
queryKey: [KEY_LIST_DOC_VERSIONS],
|
queryKey: [KEY_LIST_DOC_VERSIONS],
|
||||||
});
|
});
|
||||||
}, [modalHistory.isOpen, queryClient]);
|
}, [selectHistoryModal.isOpen, queryClient]);
|
||||||
|
|
||||||
|
const options: DropdownMenuOption[] = [
|
||||||
|
...(isSmallMobile
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
label: t('Share'),
|
||||||
|
icon: 'group',
|
||||||
|
callback: modalShare.open,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('Export'),
|
||||||
|
icon: 'download',
|
||||||
|
callback: () => {
|
||||||
|
setIsModalExportOpen(true);
|
||||||
|
},
|
||||||
|
show: !!ModalExport,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('Copy link'),
|
||||||
|
icon: 'add_link',
|
||||||
|
callback: copyDocLink,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
{
|
||||||
|
label: doc.is_favorite ? t('Unpin') : t('Pin'),
|
||||||
|
icon: 'push_pin',
|
||||||
|
callback: () => {
|
||||||
|
if (doc.is_favorite) {
|
||||||
|
removeFavoriteDoc.mutate({ id: doc.id });
|
||||||
|
} else {
|
||||||
|
makeFavoriteDoc.mutate({ id: doc.id });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
testId: `docs-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('Version history'),
|
||||||
|
icon: 'history',
|
||||||
|
disabled: !doc.abilities.versions_list,
|
||||||
|
callback: () => {
|
||||||
|
selectHistoryModal.open();
|
||||||
|
},
|
||||||
|
show: isDesktop,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: t('Copy as {{format}}', { format: 'Markdown' }),
|
||||||
|
icon: 'content_copy',
|
||||||
|
callback: () => {
|
||||||
|
void copyCurrentEditorToClipboard('markdown');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('Copy as {{format}}', { format: 'HTML' }),
|
||||||
|
icon: 'content_copy',
|
||||||
|
callback: () => {
|
||||||
|
void copyCurrentEditorToClipboard('html');
|
||||||
|
},
|
||||||
|
show: isFeatureFlagActivated('CopyAsHTML'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('Delete document'),
|
||||||
|
icon: 'delete',
|
||||||
|
disabled: !doc.abilities.destroy,
|
||||||
|
callback: () => {
|
||||||
|
setIsModalRemoveOpen(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const copyCurrentEditorToClipboard = useCopyCurrentEditorToClipboard();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -99,12 +198,55 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DocToolBoxLicence
|
{!isSmallMobile && ModalExport && (
|
||||||
doc={doc}
|
<Button
|
||||||
modalHistory={modalHistory}
|
color="tertiary-text"
|
||||||
modalShare={modalShare}
|
icon={
|
||||||
/>
|
<Icon iconName="download" $theme="primary" $variation="800" />
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
setIsModalExportOpen(true);
|
||||||
|
}}
|
||||||
|
size={isSmallMobile ? 'small' : 'medium'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<DropdownMenu options={options}>
|
||||||
|
<IconOptions
|
||||||
|
isHorizontal
|
||||||
|
$theme="primary"
|
||||||
|
$padding={{ all: 'xs' }}
|
||||||
|
$css={css`
|
||||||
|
border-radius: 4px;
|
||||||
|
&:hover {
|
||||||
|
background-color: ${colorsTokens['greyscale-100']};
|
||||||
|
}
|
||||||
|
${isSmallMobile
|
||||||
|
? css`
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid ${colorsTokens['greyscale-300']};
|
||||||
|
`
|
||||||
|
: ''}
|
||||||
|
`}
|
||||||
|
aria-label={t('Open the document options')}
|
||||||
|
/>
|
||||||
|
</DropdownMenu>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{modalShare.isOpen && (
|
||||||
|
<DocShareModal onClose={() => modalShare.close()} doc={doc} />
|
||||||
|
)}
|
||||||
|
{isModalExportOpen && ModalExport && (
|
||||||
|
<ModalExport onClose={() => setIsModalExportOpen(false)} doc={doc} />
|
||||||
|
)}
|
||||||
|
{isModalRemoveOpen && (
|
||||||
|
<ModalRemoveDoc onClose={() => setIsModalRemoveOpen(false)} doc={doc} />
|
||||||
|
)}
|
||||||
|
{selectHistoryModal.isOpen && (
|
||||||
|
<ModalSelectVersion
|
||||||
|
onClose={() => selectHistoryModal.close()}
|
||||||
|
doc={doc}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,192 +0,0 @@
|
|||||||
import { Button, useModal } from '@openfun/cunningham-react';
|
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { css } from 'styled-components';
|
|
||||||
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuOption,
|
|
||||||
Icon,
|
|
||||||
IconOptions,
|
|
||||||
} from '@/components';
|
|
||||||
import { useCunninghamTheme } from '@/cunningham';
|
|
||||||
import { ModalExport } from '@/docs/doc-export/';
|
|
||||||
import {
|
|
||||||
Doc,
|
|
||||||
KEY_DOC,
|
|
||||||
KEY_LIST_DOC,
|
|
||||||
ModalRemoveDoc,
|
|
||||||
useCopyDocLink,
|
|
||||||
useCreateFavoriteDoc,
|
|
||||||
useDeleteFavoriteDoc,
|
|
||||||
} from '@/docs/doc-management';
|
|
||||||
import {
|
|
||||||
KEY_LIST_DOC_VERSIONS,
|
|
||||||
ModalSelectVersion,
|
|
||||||
} from '@/docs/doc-versioning';
|
|
||||||
import { useAnalytics } from '@/libs';
|
|
||||||
import { useResponsiveStore } from '@/stores';
|
|
||||||
|
|
||||||
import { DocShareModal } from '../../doc-share';
|
|
||||||
import { useCopyCurrentEditorToClipboard } from '../hooks/useCopyCurrentEditorToClipboard';
|
|
||||||
|
|
||||||
type ModalType = ReturnType<typeof useModal>;
|
|
||||||
|
|
||||||
interface DocToolBoxLicenceProps {
|
|
||||||
doc: Doc;
|
|
||||||
modalHistory: ModalType;
|
|
||||||
modalShare: ModalType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DocToolBoxLicenceAGPL = ({
|
|
||||||
doc,
|
|
||||||
modalHistory,
|
|
||||||
modalShare,
|
|
||||||
}: DocToolBoxLicenceProps) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const { colorsTokens } = useCunninghamTheme();
|
|
||||||
|
|
||||||
const [isModalRemoveOpen, setIsModalRemoveOpen] = useState(false);
|
|
||||||
const [isModalExportOpen, setIsModalExportOpen] = useState(false);
|
|
||||||
|
|
||||||
const { isSmallMobile, isDesktop } = useResponsiveStore();
|
|
||||||
const copyDocLink = useCopyDocLink(doc.id);
|
|
||||||
const { isFeatureFlagActivated } = useAnalytics();
|
|
||||||
const removeFavoriteDoc = useDeleteFavoriteDoc({
|
|
||||||
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
|
||||||
});
|
|
||||||
const makeFavoriteDoc = useCreateFavoriteDoc({
|
|
||||||
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
|
||||||
});
|
|
||||||
const copyCurrentEditorToClipboard = useCopyCurrentEditorToClipboard();
|
|
||||||
|
|
||||||
const options: DropdownMenuOption[] = [
|
|
||||||
...(isSmallMobile
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
label: t('Share'),
|
|
||||||
icon: 'group',
|
|
||||||
callback: modalShare.open,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Export'),
|
|
||||||
icon: 'download',
|
|
||||||
callback: () => {
|
|
||||||
setIsModalExportOpen(true);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Copy link'),
|
|
||||||
icon: 'add_link',
|
|
||||||
callback: copyDocLink,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
{
|
|
||||||
label: doc.is_favorite ? t('Unpin') : t('Pin'),
|
|
||||||
icon: 'push_pin',
|
|
||||||
callback: () => {
|
|
||||||
if (doc.is_favorite) {
|
|
||||||
removeFavoriteDoc.mutate({ id: doc.id });
|
|
||||||
} else {
|
|
||||||
makeFavoriteDoc.mutate({ id: doc.id });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
testId: `docs-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Version history'),
|
|
||||||
icon: 'history',
|
|
||||||
disabled: !doc.abilities.versions_list,
|
|
||||||
callback: () => {
|
|
||||||
modalHistory.open();
|
|
||||||
},
|
|
||||||
show: isDesktop,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
label: t('Copy as {{format}}', { format: 'Markdown' }),
|
|
||||||
icon: 'content_copy',
|
|
||||||
callback: () => {
|
|
||||||
void copyCurrentEditorToClipboard('markdown');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Copy as {{format}}', { format: 'HTML' }),
|
|
||||||
icon: 'content_copy',
|
|
||||||
callback: () => {
|
|
||||||
void copyCurrentEditorToClipboard('html');
|
|
||||||
},
|
|
||||||
show: isFeatureFlagActivated('CopyAsHTML'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Delete document'),
|
|
||||||
icon: 'delete',
|
|
||||||
disabled: !doc.abilities.destroy,
|
|
||||||
callback: () => {
|
|
||||||
setIsModalRemoveOpen(true);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (modalHistory.isOpen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void queryClient.resetQueries({
|
|
||||||
queryKey: [KEY_LIST_DOC_VERSIONS],
|
|
||||||
});
|
|
||||||
}, [modalHistory.isOpen, queryClient]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{!isSmallMobile && (
|
|
||||||
<Button
|
|
||||||
color="tertiary-text"
|
|
||||||
icon={<Icon iconName="download" $theme="primary" $variation="800" />}
|
|
||||||
onClick={() => {
|
|
||||||
setIsModalExportOpen(true);
|
|
||||||
}}
|
|
||||||
size={isSmallMobile ? 'small' : 'medium'}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<DropdownMenu options={options}>
|
|
||||||
<IconOptions
|
|
||||||
isHorizontal
|
|
||||||
$theme="primary"
|
|
||||||
$padding={{ all: 'xs' }}
|
|
||||||
$css={css`
|
|
||||||
border-radius: 4px;
|
|
||||||
&:hover {
|
|
||||||
background-color: ${colorsTokens['greyscale-100']};
|
|
||||||
}
|
|
||||||
${isSmallMobile
|
|
||||||
? css`
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid ${colorsTokens['greyscale-300']};
|
|
||||||
`
|
|
||||||
: ''}
|
|
||||||
`}
|
|
||||||
aria-label={t('Open the document options')}
|
|
||||||
/>
|
|
||||||
</DropdownMenu>
|
|
||||||
|
|
||||||
{modalShare.isOpen && (
|
|
||||||
<DocShareModal onClose={() => modalShare.close()} doc={doc} />
|
|
||||||
)}
|
|
||||||
{isModalExportOpen && (
|
|
||||||
<ModalExport onClose={() => setIsModalExportOpen(false)} doc={doc} />
|
|
||||||
)}
|
|
||||||
{isModalRemoveOpen && (
|
|
||||||
<ModalRemoveDoc onClose={() => setIsModalRemoveOpen(false)} doc={doc} />
|
|
||||||
)}
|
|
||||||
{modalHistory.isOpen && (
|
|
||||||
<ModalSelectVersion onClose={() => modalHistory.close()} doc={doc} />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
import { useModal } from '@openfun/cunningham-react';
|
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { css } from 'styled-components';
|
|
||||||
|
|
||||||
import { DropdownMenu, DropdownMenuOption, IconOptions } from '@/components';
|
|
||||||
import { useCunninghamTheme } from '@/cunningham';
|
|
||||||
import {
|
|
||||||
Doc,
|
|
||||||
KEY_DOC,
|
|
||||||
KEY_LIST_DOC,
|
|
||||||
ModalRemoveDoc,
|
|
||||||
useCopyDocLink,
|
|
||||||
useCreateFavoriteDoc,
|
|
||||||
useDeleteFavoriteDoc,
|
|
||||||
} from '@/docs/doc-management';
|
|
||||||
import {
|
|
||||||
KEY_LIST_DOC_VERSIONS,
|
|
||||||
ModalSelectVersion,
|
|
||||||
} from '@/docs/doc-versioning';
|
|
||||||
import { useAnalytics } from '@/libs';
|
|
||||||
import { useResponsiveStore } from '@/stores';
|
|
||||||
|
|
||||||
import { DocShareModal } from '../../doc-share';
|
|
||||||
import { useCopyCurrentEditorToClipboard } from '../hooks/useCopyCurrentEditorToClipboard';
|
|
||||||
|
|
||||||
type ModalType = ReturnType<typeof useModal>;
|
|
||||||
|
|
||||||
interface DocToolBoxLicenceProps {
|
|
||||||
doc: Doc;
|
|
||||||
modalHistory: ModalType;
|
|
||||||
modalShare: ModalType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DocToolBoxLicenceMIT = ({
|
|
||||||
doc,
|
|
||||||
modalHistory,
|
|
||||||
modalShare,
|
|
||||||
}: DocToolBoxLicenceProps) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const { colorsTokens } = useCunninghamTheme();
|
|
||||||
|
|
||||||
const [isModalRemoveOpen, setIsModalRemoveOpen] = useState(false);
|
|
||||||
|
|
||||||
const { isSmallMobile, isDesktop } = useResponsiveStore();
|
|
||||||
const copyDocLink = useCopyDocLink(doc.id);
|
|
||||||
const { isFeatureFlagActivated } = useAnalytics();
|
|
||||||
const removeFavoriteDoc = useDeleteFavoriteDoc({
|
|
||||||
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
|
||||||
});
|
|
||||||
const makeFavoriteDoc = useCreateFavoriteDoc({
|
|
||||||
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
|
||||||
});
|
|
||||||
const copyCurrentEditorToClipboard = useCopyCurrentEditorToClipboard();
|
|
||||||
|
|
||||||
const options: DropdownMenuOption[] = [
|
|
||||||
...(isSmallMobile
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
label: t('Share'),
|
|
||||||
icon: 'group',
|
|
||||||
callback: modalShare.open,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Copy link'),
|
|
||||||
icon: 'add_link',
|
|
||||||
callback: copyDocLink,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
{
|
|
||||||
label: doc.is_favorite ? t('Unpin') : t('Pin'),
|
|
||||||
icon: 'push_pin',
|
|
||||||
callback: () => {
|
|
||||||
if (doc.is_favorite) {
|
|
||||||
removeFavoriteDoc.mutate({ id: doc.id });
|
|
||||||
} else {
|
|
||||||
makeFavoriteDoc.mutate({ id: doc.id });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
testId: `docs-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Version history'),
|
|
||||||
icon: 'history',
|
|
||||||
disabled: !doc.abilities.versions_list,
|
|
||||||
callback: () => {
|
|
||||||
modalHistory.open();
|
|
||||||
},
|
|
||||||
show: isDesktop,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
label: t('Copy as {{format}}', { format: 'Markdown' }),
|
|
||||||
icon: 'content_copy',
|
|
||||||
callback: () => {
|
|
||||||
void copyCurrentEditorToClipboard('markdown');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Copy as {{format}}', { format: 'HTML' }),
|
|
||||||
icon: 'content_copy',
|
|
||||||
callback: () => {
|
|
||||||
void copyCurrentEditorToClipboard('html');
|
|
||||||
},
|
|
||||||
show: isFeatureFlagActivated('CopyAsHTML'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('Delete document'),
|
|
||||||
icon: 'delete',
|
|
||||||
disabled: !doc.abilities.destroy,
|
|
||||||
callback: () => {
|
|
||||||
setIsModalRemoveOpen(true);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (modalHistory.isOpen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void queryClient.resetQueries({
|
|
||||||
queryKey: [KEY_LIST_DOC_VERSIONS],
|
|
||||||
});
|
|
||||||
}, [modalHistory.isOpen, queryClient]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<DropdownMenu options={options}>
|
|
||||||
<IconOptions
|
|
||||||
isHorizontal
|
|
||||||
$theme="primary"
|
|
||||||
$padding={{ all: 'xs' }}
|
|
||||||
$css={css`
|
|
||||||
border-radius: 4px;
|
|
||||||
&:hover {
|
|
||||||
background-color: ${colorsTokens['greyscale-100']};
|
|
||||||
}
|
|
||||||
${isSmallMobile
|
|
||||||
? css`
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid ${colorsTokens['greyscale-300']};
|
|
||||||
`
|
|
||||||
: ''}
|
|
||||||
`}
|
|
||||||
aria-label={t('Open the document options')}
|
|
||||||
/>
|
|
||||||
</DropdownMenu>
|
|
||||||
|
|
||||||
{modalShare.isOpen && (
|
|
||||||
<DocShareModal onClose={() => modalShare.close()} doc={doc} />
|
|
||||||
)}
|
|
||||||
{isModalRemoveOpen && (
|
|
||||||
<ModalRemoveDoc onClose={() => setIsModalRemoveOpen(false)} doc={doc} />
|
|
||||||
)}
|
|
||||||
{modalHistory.isOpen && (
|
|
||||||
<ModalSelectVersion onClose={() => modalHistory.close()} doc={doc} />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user