♻️(frontend) redirect to doc after duplicate

When we duplicate a document from a document page,
we now redirect the user to the newly created
document.
This commit is contained in:
Anthony LC
2025-07-15 12:42:09 +02:00
parent ef6d6c6a59
commit 966e514c5a
6 changed files with 40 additions and 44 deletions

View File

@@ -10,6 +10,7 @@ and this project adheres to
### Changed ### Changed
- ♻️(frontend) redirect to doc after duplicate #1175
- 🔧(project) change env.d system by using local files #1200 - 🔧(project) change env.d system by using local files #1200
### Fixed ### Fixed

View File

@@ -442,9 +442,10 @@ test.describe('Doc Header', () => {
page.getByText('Document duplicated successfully!'), page.getByText('Document duplicated successfully!'),
).toBeVisible(); ).toBeVisible();
await page.goto('/');
const duplicateTitle = 'Copy of ' + docTitle; const duplicateTitle = 'Copy of ' + docTitle;
await verifyDocName(page, duplicateTitle);
await page.goto('/');
const row = await getGridRow(page, duplicateTitle); const row = await getGridRow(page, duplicateTitle);
@@ -477,9 +478,12 @@ test.describe('Doc Header', () => {
page.getByText('Document duplicated successfully!'), page.getByText('Document duplicated successfully!'),
).toBeVisible(); ).toBeVisible();
const duplicateDuplicateTitle = 'Copy of ' + childTitle; const duplicateTitle = 'Copy of ' + childTitle;
await verifyDocName(page, duplicateTitle);
await expect( await expect(
page.getByTestId('doc-tree').getByText(duplicateDuplicateTitle), page.getByTestId('doc-tree').getByText(duplicateTitle),
).toBeVisible(); ).toBeVisible();
}); });
}); });

View File

@@ -32,6 +32,13 @@ jest.mock('@/features/docs/doc-export/', () => ({
ModalExport: () => <span>ModalExport</span>, ModalExport: () => <span>ModalExport</span>,
})); }));
jest.mock('next/router', () => ({
...jest.requireActual('next/router'),
useRouter: () => ({
push: jest.fn(),
}),
}));
const doc = { const doc = {
nb_accesses: 1, nb_accesses: 1,
abilities: { abilities: {

View File

@@ -1,11 +1,7 @@
import { useTreeContext } from '@gouvfr-lasuite/ui-kit'; import { useTreeContext } from '@gouvfr-lasuite/ui-kit';
import { import { Button, useModal } from '@openfun/cunningham-react';
Button,
VariantType,
useModal,
useToastProvider,
} from '@openfun/cunningham-react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { css } from 'styled-components'; import { css } from 'styled-components';
@@ -62,7 +58,7 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
}, [doc, treeContext?.root]); }, [doc, treeContext?.root]);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { toast } = useToastProvider(); const router = useRouter();
const { spacingsTokens, colorsTokens } = useCunninghamTheme(); const { spacingsTokens, colorsTokens } = useCunninghamTheme();
@@ -74,15 +70,8 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
const { isSmallMobile, isDesktop } = useResponsiveStore(); const { isSmallMobile, isDesktop } = useResponsiveStore();
const copyDocLink = useCopyDocLink(doc.id); const copyDocLink = useCopyDocLink(doc.id);
const { mutate: duplicateDoc } = useDuplicateDoc({ const { mutate: duplicateDoc } = useDuplicateDoc({
onSuccess: () => { onSuccess: (data) => {
toast(t('Document duplicated successfully!'), VariantType.SUCCESS, { void router.push(`/docs/${data.id}`);
duration: 3000,
});
},
onError: () => {
toast(t('Failed to duplicate the document...'), VariantType.ERROR, {
duration: 3000,
});
}, },
}); });
const { isFeatureFlagActivated } = useAnalytics(); const { isFeatureFlagActivated } = useAnalytics();

View File

@@ -1,13 +1,14 @@
import { VariantType, useToastProvider } from '@openfun/cunningham-react';
import { import {
UseMutationOptions, UseMutationOptions,
useMutation, useMutation,
useQueryClient, useQueryClient,
} from '@tanstack/react-query'; } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import * as Y from 'yjs'; import * as Y from 'yjs';
import { APIError, errorCauses, fetchAPI } from '@/api'; import { APIError, errorCauses, fetchAPI } from '@/api';
import { toBase64 } from '@/docs/doc-editor'; import { toBase64 } from '@/docs/doc-editor';
import { KEY_DOC_TREE } from '@/docs/doc-tree';
import { KEY_LIST_DOC_VERSIONS } from '@/docs/doc-versioning'; import { KEY_LIST_DOC_VERSIONS } from '@/docs/doc-versioning';
import { useProviderStore } from '../stores'; import { useProviderStore } from '../stores';
@@ -52,9 +53,10 @@ type DuplicateDocOptions = UseMutationOptions<
DuplicateDocParams DuplicateDocParams
>; >;
export function useDuplicateDoc(options: DuplicateDocOptions) { export function useDuplicateDoc(options?: DuplicateDocOptions) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { toast } = useToastProvider();
const { t } = useTranslation();
const { provider } = useProviderStore(); const { provider } = useProviderStore();
const { mutateAsync: updateDoc } = useUpdateDoc({ const { mutateAsync: updateDoc } = useUpdateDoc({
@@ -86,10 +88,19 @@ export function useDuplicateDoc(options: DuplicateDocOptions) {
void queryClient.resetQueries({ void queryClient.resetQueries({
queryKey: [KEY_LIST_DOC], queryKey: [KEY_LIST_DOC],
}); });
void queryClient.resetQueries({
queryKey: [KEY_DOC_TREE], toast(t('Document duplicated successfully!'), VariantType.SUCCESS, {
duration: 3000,
}); });
void options.onSuccess?.(data, variables, context);
void options?.onSuccess?.(data, variables, context);
},
onError: (error, variables, context) => {
toast(t('Failed to duplicate the document...'), VariantType.ERROR, {
duration: 3000,
});
void options?.onError?.(error, variables, context);
}, },
}); });
} }

View File

@@ -1,8 +1,4 @@
import { import { useModal } from '@openfun/cunningham-react';
VariantType,
useModal,
useToastProvider,
} from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { DropdownMenu, DropdownMenuOption, Icon } from '@/components'; import { DropdownMenu, DropdownMenuOption, Icon } from '@/components';
@@ -25,21 +21,9 @@ export const DocsGridActions = ({
openShareModal, openShareModal,
}: DocsGridActionsProps) => { }: DocsGridActionsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { toast } = useToastProvider();
const deleteModal = useModal(); const deleteModal = useModal();
const { mutate: duplicateDoc } = useDuplicateDoc({ const { mutate: duplicateDoc } = useDuplicateDoc();
onSuccess: () => {
toast(t('Document duplicated successfully!'), VariantType.SUCCESS, {
duration: 3000,
});
},
onError: () => {
toast(t('Failed to duplicate the document...'), VariantType.ERROR, {
duration: 3000,
});
},
});
const removeFavoriteDoc = useDeleteFavoriteDoc({ const removeFavoriteDoc = useDeleteFavoriteDoc({
listInvalideQueries: [KEY_LIST_DOC], listInvalideQueries: [KEY_LIST_DOC],