🚚(frontend) move modal Share directly to concern component

To keep consistency with the other modals, we move
the share modal directly to the
DocsGridActions component. This way, we avoid
having to pass down the openShareModal function
from parent components and keep the logic related
to sharing a doc encapsulated within the
concern component.
This commit is contained in:
Anthony LC
2026-02-12 17:19:54 +01:00
parent a51ceeb409
commit 53985f77f3
4 changed files with 57 additions and 72 deletions

View File

@@ -12,19 +12,18 @@ import {
useDeleteFavoriteDoc, useDeleteFavoriteDoc,
useDuplicateDoc, useDuplicateDoc,
} from '@/docs/doc-management'; } from '@/docs/doc-management';
import { DocShareModal } from '@/docs/doc-share';
interface DocsGridActionsProps { interface DocsGridActionsProps {
doc: Doc; doc: Doc;
openShareModal?: () => void;
} }
export const DocsGridActions = ({ export const DocsGridActions = ({ doc }: DocsGridActionsProps) => {
doc,
openShareModal,
}: DocsGridActionsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const deleteModal = useModal(); const deleteModal = useModal();
const shareModal = useModal();
const { mutate: duplicateDoc } = useDuplicateDoc(); const { mutate: duplicateDoc } = useDuplicateDoc();
const removeFavoriteDoc = useDeleteFavoriteDoc({ const removeFavoriteDoc = useDeleteFavoriteDoc({
@@ -52,7 +51,7 @@ export const DocsGridActions = ({
label: t('Share'), label: t('Share'),
icon: 'group', icon: 'group',
callback: () => { callback: () => {
openShareModal?.(); shareModal.open();
}, },
testId: `docs-grid-actions-share-${doc.id}`, testId: `docs-grid-actions-share-${doc.id}`,
@@ -114,6 +113,9 @@ export const DocsGridActions = ({
{deleteModal.isOpen && ( {deleteModal.isOpen && (
<ModalRemoveDoc onClose={deleteModal.onClose} doc={doc} /> <ModalRemoveDoc onClose={deleteModal.onClose} doc={doc} />
)} )}
{shareModal.isOpen && (
<DocShareModal doc={doc} onClose={shareModal.close} />
)}
</> </>
); );
}; };

View File

@@ -1,4 +1,4 @@
import { Tooltip, useModal } from '@gouvfr-lasuite/cunningham-react'; import { Tooltip } from '@gouvfr-lasuite/cunningham-react';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { KeyboardEvent } from 'react'; import { KeyboardEvent } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -8,7 +8,6 @@ import { Box, Icon, StyledLink, Text } from '@/components';
import { useConfig } from '@/core'; import { useConfig } from '@/core';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
import { Doc, LinkReach, SimpleDocItem } from '@/docs/doc-management'; import { Doc, LinkReach, SimpleDocItem } from '@/docs/doc-management';
import { DocShareModal } from '@/docs/doc-share';
import { useDate } from '@/hooks'; import { useDate } from '@/hooks';
import { useResponsiveStore } from '@/stores'; import { useResponsiveStore } from '@/stores';
@@ -32,15 +31,10 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
const { isDesktop } = useResponsiveStore(); const { isDesktop } = useResponsiveStore();
const { flexLeft, flexRight } = useResponsiveDocGrid(); const { flexLeft, flexRight } = useResponsiveDocGrid();
const { spacingsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
const shareModal = useModal();
const isPublic = doc.link_reach === LinkReach.PUBLIC; const isPublic = doc.link_reach === LinkReach.PUBLIC;
const isAuthenticated = doc.link_reach === LinkReach.AUTHENTICATED; const isAuthenticated = doc.link_reach === LinkReach.AUTHENTICATED;
const isShared = isPublic || isAuthenticated; const isShared = isPublic || isAuthenticated;
const handleShareClick = () => {
shareModal.open();
};
const handleKeyDown = (e: KeyboardEvent) => { const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') { if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault(); e.preventDefault();
@@ -173,23 +167,16 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
<Box $direction="row" $align="center" $gap={spacingsTokens.lg}> <Box $direction="row" $align="center" $gap={spacingsTokens.lg}>
{isDesktop && ( {isDesktop && (
<DocsGridItemSharedButton <DocsGridItemSharedButton doc={doc} disabled={isInTrashbin} />
doc={doc}
handleClick={handleShareClick}
disabled={isInTrashbin}
/>
)} )}
{isInTrashbin ? ( {isInTrashbin ? (
<DocsGridTrashbinActions doc={doc} /> <DocsGridTrashbinActions doc={doc} />
) : ( ) : (
<DocsGridActions doc={doc} openShareModal={handleShareClick} /> <DocsGridActions doc={doc} />
)} )}
</Box> </Box>
</Box> </Box>
</Box> </Box>
{shareModal.isOpen && (
<DocShareModal doc={doc} onClose={shareModal.close} />
)}
</> </>
); );
}; };

View File

@@ -1,65 +1,67 @@
import { Button, Tooltip } from '@gouvfr-lasuite/cunningham-react'; import { Button, Tooltip, useModal } from '@gouvfr-lasuite/cunningham-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Box, Icon, Text } from '@/components'; import { Box, Icon, Text } from '@/components';
import { Doc } from '@/docs/doc-management'; import { Doc } from '@/docs/doc-management';
import { DocShareModal } from '@/docs/doc-share';
type Props = { type Props = {
doc: Doc; doc: Doc;
handleClick: () => void;
disabled: boolean; disabled: boolean;
}; };
export const DocsGridItemSharedButton = ({ export const DocsGridItemSharedButton = ({ doc, disabled }: Props) => {
doc,
handleClick,
disabled,
}: Props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const sharedCount = doc.nb_accesses_direct; const sharedCount = doc.nb_accesses_direct;
const isShared = sharedCount - 1 > 0; const isShared = sharedCount - 1 > 0;
const shareModal = useModal();
if (!isShared) { if (!isShared) {
return <Box $minWidth="50px">&nbsp;</Box>; return <Box $minWidth="50px">&nbsp;</Box>;
} }
return ( return (
<Tooltip <>
content={ <Tooltip
<Text $textAlign="center"> content={
{t('Shared with {{count}} users', { count: sharedCount })} <Text $textAlign="center">
</Text> {t('Shared with {{count}} users', { count: sharedCount })}
} </Text>
placement="top"
className="--docs--doc-tooltip-grid-item-shared-button"
>
<Button
className="--docs--doc-grid-item-shared-button"
aria-label={t('Open the sharing settings for the document')}
data-testid={`docs-grid-item-shared-button-${doc.id}`}
style={{
padding: `0 var(--c--globals--spacings--xxxs) 0 var(--c--globals--spacings--xxxs)`,
}}
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
handleClick();
}}
color="brand"
variant="secondary"
size="nano"
icon={
<Icon
$theme="brand"
$variation="secondary"
iconName="group"
disabled={disabled}
variant="filled"
/>
} }
disabled={disabled} placement="top"
className="--docs--doc-tooltip-grid-item-shared-button"
> >
{sharedCount} <Button
</Button> className="--docs--doc-grid-item-shared-button"
</Tooltip> aria-label={t('Open the sharing settings for the document')}
data-testid={`docs-grid-item-shared-button-${doc.id}`}
style={{
padding: `0 var(--c--globals--spacings--xxxs) 0 var(--c--globals--spacings--xxxs)`,
}}
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
shareModal.open();
}}
color="brand"
variant="secondary"
size="nano"
icon={
<Icon
$theme="brand"
$variation="secondary"
iconName="group"
disabled={disabled}
variant="filled"
/>
}
disabled={disabled}
>
{sharedCount}
</Button>
</Tooltip>
{shareModal.isOpen && (
<DocShareModal doc={doc} onClose={shareModal.close} />
)}
</>
); );
}; };

View File

@@ -1,4 +1,3 @@
import { useModal } from '@gouvfr-lasuite/cunningham-react';
import { t } from 'i18next'; import { t } from 'i18next';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { css } from 'styled-components'; import { css } from 'styled-components';
@@ -6,7 +5,6 @@ import { css } from 'styled-components';
import { Box, StyledLink } from '@/components'; import { Box, StyledLink } from '@/components';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
import { Doc, SimpleDocItem } from '@/docs/doc-management'; import { Doc, SimpleDocItem } from '@/docs/doc-management';
import { DocShareModal } from '@/docs/doc-share';
import { DocsGridActions } from '@/docs/docs-grid'; import { DocsGridActions } from '@/docs/docs-grid';
import { useResponsiveStore } from '@/stores'; import { useResponsiveStore } from '@/stores';
@@ -15,7 +13,6 @@ type LeftPanelFavoriteItemProps = {
}; };
export const LeftPanelFavoriteItem = ({ doc }: LeftPanelFavoriteItemProps) => { export const LeftPanelFavoriteItem = ({ doc }: LeftPanelFavoriteItemProps) => {
const shareModal = useModal();
const { colorsTokens, spacingsTokens } = useCunninghamTheme(); const { colorsTokens, spacingsTokens } = useCunninghamTheme();
const { isDesktop } = useResponsiveStore(); const { isDesktop } = useResponsiveStore();
@@ -61,11 +58,8 @@ export const LeftPanelFavoriteItem = ({ doc }: LeftPanelFavoriteItemProps) => {
<SimpleDocItem showAccesses doc={doc} /> <SimpleDocItem showAccesses doc={doc} />
</StyledLink> </StyledLink>
<Box className="pinned-actions" $align="center"> <Box className="pinned-actions" $align="center">
<DocsGridActions doc={doc} openShareModal={shareModal.open} /> <DocsGridActions doc={doc} />
</Box> </Box>
{shareModal.isOpen && (
<DocShareModal doc={doc} onClose={shareModal.close} />
)}
</Box> </Box>
); );
}; };