♻️(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
- ♻️(frontend) redirect to doc after duplicate #1175
- 🔧(project) change env.d system by using local files #1200
### Fixed

View File

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

View File

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

View File

@@ -1,11 +1,7 @@
import { useTreeContext } from '@gouvfr-lasuite/ui-kit';
import {
Button,
VariantType,
useModal,
useToastProvider,
} from '@openfun/cunningham-react';
import { Button, useModal } from '@openfun/cunningham-react';
import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
@@ -62,7 +58,7 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
}, [doc, treeContext?.root]);
const queryClient = useQueryClient();
const { toast } = useToastProvider();
const router = useRouter();
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
@@ -74,15 +70,8 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
const { isSmallMobile, isDesktop } = useResponsiveStore();
const copyDocLink = useCopyDocLink(doc.id);
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,
});
onSuccess: (data) => {
void router.push(`/docs/${data.id}`);
},
});
const { isFeatureFlagActivated } = useAnalytics();

View File

@@ -1,13 +1,14 @@
import { VariantType, useToastProvider } from '@openfun/cunningham-react';
import {
UseMutationOptions,
useMutation,
useQueryClient,
} from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import * as Y from 'yjs';
import { APIError, errorCauses, fetchAPI } from '@/api';
import { toBase64 } from '@/docs/doc-editor';
import { KEY_DOC_TREE } from '@/docs/doc-tree';
import { KEY_LIST_DOC_VERSIONS } from '@/docs/doc-versioning';
import { useProviderStore } from '../stores';
@@ -52,9 +53,10 @@ type DuplicateDocOptions = UseMutationOptions<
DuplicateDocParams
>;
export function useDuplicateDoc(options: DuplicateDocOptions) {
export function useDuplicateDoc(options?: DuplicateDocOptions) {
const queryClient = useQueryClient();
const { toast } = useToastProvider();
const { t } = useTranslation();
const { provider } = useProviderStore();
const { mutateAsync: updateDoc } = useUpdateDoc({
@@ -86,10 +88,19 @@ export function useDuplicateDoc(options: DuplicateDocOptions) {
void queryClient.resetQueries({
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 {
VariantType,
useModal,
useToastProvider,
} from '@openfun/cunningham-react';
import { useModal } from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next';
import { DropdownMenu, DropdownMenuOption, Icon } from '@/components';
@@ -25,21 +21,9 @@ export const DocsGridActions = ({
openShareModal,
}: DocsGridActionsProps) => {
const { t } = useTranslation();
const { toast } = useToastProvider();
const deleteModal = useModal();
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 { mutate: duplicateDoc } = useDuplicateDoc();
const removeFavoriteDoc = useDeleteFavoriteDoc({
listInvalideQueries: [KEY_LIST_DOC],