Skip to content

Commit de4d117

Browse files
committed
✨(frontend) can restore from trashbin list actions
We can now restore a doc from the trashbin list actions.
1 parent 37138c1 commit de4d117

File tree

19 files changed

+332
-64
lines changed

19 files changed

+332
-64
lines changed

src/frontend/apps/e2e/__tests__/app-impress/doc-trashbin.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ test.describe('Doc Trashbin', () => {
2929
const row1 = await getGridRow(page, title1);
3030
await clickInGridMenu(page, row1, 'Delete');
3131
await page.getByRole('button', { name: 'Delete document' }).click();
32+
await expect(row1.getByText(title1)).toBeHidden();
3233

3334
const row2 = await getGridRow(page, title2);
3435
await clickInGridMenu(page, row2, 'Delete');
3536
await page.getByRole('button', { name: 'Delete document' }).click();
37+
await expect(row2.getByText(title2)).toBeHidden();
3638

3739
await page.getByRole('link', { name: 'Trashbin' }).click();
3840

@@ -51,5 +53,25 @@ test.describe('Doc Trashbin', () => {
5153
name: 'Open the sharing settings for the document',
5254
}),
5355
).toBeDisabled();
56+
57+
await clickInGridMenu(page, row2, 'Restore');
58+
59+
await expect(row2.getByText(title2)).toBeHidden();
60+
await page.getByRole('link', { name: 'All docs' }).click();
61+
const row2Restored = await getGridRow(page, title2);
62+
await expect(row2Restored.getByText(title2)).toBeVisible();
63+
await row2Restored.getByRole('link', { name: /Open document/ }).click();
64+
65+
await verifyDocName(page, title2);
66+
await page.getByRole('button', { name: 'Back to homepage' }).click();
67+
await expect(row2.getByText(title2)).toBeVisible();
68+
await expect(
69+
row2.getByRole('button', {
70+
name: 'Open the sharing settings for the document',
71+
}),
72+
).toBeEnabled();
73+
74+
await page.getByRole('link', { name: 'Trashbin' }).click();
75+
await expect(row2.getByText(title2)).toBeHidden();
5476
});
5577
});

src/frontend/apps/impress/src/components/TextErrors.tsx

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,54 @@ export const TextErrors = ({
2525
canClose = false,
2626
...textProps
2727
}: TextErrorsProps) => {
28-
const { t } = useTranslation();
29-
3028
return (
3129
<AlertStyled
3230
canClose={canClose}
3331
type={VariantType.ERROR}
3432
icon={icon}
3533
className="--docs--text-errors"
3634
>
37-
<Box $direction="column" $gap="0.2rem">
38-
{causes &&
39-
causes.map((cause, i) => (
40-
<Text
41-
key={`causes-${i}`}
42-
$theme="danger"
43-
$variation="600"
44-
$textAlign="center"
45-
{...textProps}
46-
>
47-
{cause}
48-
</Text>
49-
))}
35+
<TextOnlyErrors
36+
causes={causes}
37+
defaultMessage={defaultMessage}
38+
{...textProps}
39+
/>
40+
</AlertStyled>
41+
);
42+
};
43+
44+
export const TextOnlyErrors = ({
45+
causes,
46+
defaultMessage,
47+
...textProps
48+
}: TextErrorsProps) => {
49+
const { t } = useTranslation();
5050

51-
{!causes && (
51+
return (
52+
<Box $direction="column" $gap="0.2rem">
53+
{causes &&
54+
causes.map((cause, i) => (
5255
<Text
56+
key={`causes-${i}`}
5357
$theme="danger"
5458
$variation="600"
5559
$textAlign="center"
5660
{...textProps}
5761
>
58-
{defaultMessage || t('Something bad happens, please retry.')}
62+
{cause}
5963
</Text>
60-
)}
61-
</Box>
62-
</AlertStyled>
64+
))}
65+
66+
{!causes && (
67+
<Text
68+
$theme="danger"
69+
$variation="600"
70+
$textAlign="center"
71+
{...textProps}
72+
>
73+
{defaultMessage || t('Something bad happens, please retry.')}
74+
</Text>
75+
)}
76+
</Box>
6377
);
6478
};

src/frontend/apps/impress/src/components/dropdown-menu/DropdownMenu.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { HorizontalSeparator } from '@gouvfr-lasuite/ui-kit';
22
import {
33
Fragment,
44
PropsWithChildren,
5+
ReactNode,
56
useCallback,
67
useEffect,
78
useRef,
@@ -15,7 +16,7 @@ import { useCunninghamTheme } from '@/cunningham';
1516
import { useDropdownKeyboardNav } from './hook/useDropdownKeyboardNav';
1617

1718
export type DropdownMenuOption = {
18-
icon?: string;
19+
icon?: ReactNode;
1920
label: string;
2021
testId?: string;
2122
value?: string;
@@ -220,7 +221,7 @@ export const DropdownMenu = ({
220221
$align="center"
221222
$gap={spacingsTokens['base']}
222223
>
223-
{option.icon && (
224+
{option.icon && typeof option.icon === 'string' && (
224225
<Icon
225226
$size="20px"
226227
$theme="greyscale"
@@ -229,6 +230,9 @@ export const DropdownMenu = ({
229230
aria-hidden="true"
230231
/>
231232
)}
233+
{option.icon &&
234+
typeof option.icon !== 'string' &&
235+
option.icon}
232236
<Text $variation={isDisabled ? '400' : '1000'}>
233237
{option.label}
234238
</Text>

src/frontend/apps/impress/src/components/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
export * from './modal/AlertModal';
21
export * from './Box';
32
export * from './BoxButton';
43
export * from './Card';
@@ -9,7 +8,7 @@ export * from './Icon';
98
export * from './InfiniteScroll';
109
export * from './Link';
1110
export * from './Loading';
12-
export * from './modal/SideModal';
11+
export * from './modal';
1312
export * from './separators';
1413
export * from './Text';
1514
export * from './TextErrors';

src/frontend/apps/impress/src/components/modal/ButtonCloseModal.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React from 'react';
33

44
import { Box } from '@/components';
55

6-
const ButtonCloseModal = (props: ButtonProps) => {
6+
export const ButtonCloseModal = (props: ButtonProps) => {
77
return (
88
<Button
99
type="button"
@@ -18,5 +18,3 @@ const ButtonCloseModal = (props: ButtonProps) => {
1818
/>
1919
);
2020
};
21-
22-
export default ButtonCloseModal;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './AlertModal';
2+
export * from './ButtonCloseModal';

src/frontend/apps/impress/src/features/docs/doc-export/components/ModalExport.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ import { cloneElement, isValidElement, useMemo, useState } from 'react';
1616
import { useTranslation } from 'react-i18next';
1717
import { css } from 'styled-components';
1818

19-
import { Box, Text } from '@/components';
20-
import ButtonCloseModal from '@/components/modal/ButtonCloseModal';
19+
import { Box, ButtonCloseModal, Text } from '@/components';
2120
import { useEditorStore } from '@/docs/doc-editor';
2221
import { Doc, useTrans } from '@/docs/doc-management';
2322

src/frontend/apps/impress/src/features/docs/doc-management/api/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export * from './useDeleteFavoriteDoc';
55
export * from './useDoc';
66
export * from './useDocOptions';
77
export * from './useDocs';
8-
export * from './useSubDocs';
98
export * from './useDuplicateDoc';
9+
export * from './useRestoreDoc';
10+
export * from './useSubDocs';
1011
export * from './useUpdateDoc';
1112
export * from './useUpdateDocLink';

src/frontend/apps/impress/src/features/docs/doc-management/api/useDocs.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query';
33
import {
44
APIError,
55
APIList,
6+
InfiniteQueryConfig,
67
errorCauses,
78
fetchAPI,
89
useAPIInfiniteQuery,
@@ -54,17 +55,20 @@ export const getDocs = async (params: DocsParams): Promise<DocsResponse> => {
5455

5556
export const KEY_LIST_DOC = 'docs';
5657

57-
export function useDocs(
58-
params: DocsParams,
59-
queryConfig?: UseQueryOptions<DocsResponse, APIError, DocsResponse>,
60-
) {
58+
type UseDocsOptions = UseQueryOptions<DocsResponse, APIError, DocsResponse>;
59+
type UseInfiniteDocsOptions = InfiniteQueryConfig<DocsResponse>;
60+
61+
export function useDocs(params: DocsParams, queryConfig?: UseDocsOptions) {
6162
return useQuery<DocsResponse, APIError, DocsResponse>({
6263
queryKey: [KEY_LIST_DOC, params],
6364
queryFn: () => getDocs(params),
6465
...queryConfig,
6566
});
6667
}
6768

68-
export const useInfiniteDocs = (params: DocsParams) => {
69-
return useAPIInfiniteQuery(KEY_LIST_DOC, getDocs, params);
69+
export const useInfiniteDocs = (
70+
params: DocsParams,
71+
queryConfig?: UseInfiniteDocsOptions,
72+
) => {
73+
return useAPIInfiniteQuery(KEY_LIST_DOC, getDocs, params, queryConfig);
7074
};

src/frontend/apps/impress/src/features/docs/doc-management/api/useRemoveDoc.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import {
66

77
import { APIError, errorCauses, fetchAPI } from '@/api';
88

9-
import { KEY_LIST_DOC } from './useDocs';
10-
119
interface RemoveDocProps {
1210
docId: string;
1311
}
@@ -24,14 +22,22 @@ export const removeDoc = async ({ docId }: RemoveDocProps): Promise<void> => {
2422

2523
type UseRemoveDocOptions = UseMutationOptions<void, APIError, RemoveDocProps>;
2624

27-
export const useRemoveDoc = (options?: UseRemoveDocOptions) => {
25+
export const useRemoveDoc = ({
26+
listInvalidQueries,
27+
options,
28+
}: {
29+
listInvalidQueries?: string[];
30+
options?: UseRemoveDocOptions;
31+
}) => {
2832
const queryClient = useQueryClient();
2933
return useMutation<void, APIError, RemoveDocProps>({
3034
mutationFn: removeDoc,
3135
...options,
3236
onSuccess: (data, variables, context) => {
33-
void queryClient.invalidateQueries({
34-
queryKey: [KEY_LIST_DOC],
37+
listInvalidQueries?.forEach((queryKey) => {
38+
void queryClient.invalidateQueries({
39+
queryKey: [queryKey],
40+
});
3541
});
3642
if (options?.onSuccess) {
3743
void options.onSuccess(data, variables, context);

0 commit comments

Comments
 (0)