diff --git a/src/frontend/packages/lib_markdown/src/components/MarkdownEditor/index.spec.tsx b/src/frontend/packages/lib_markdown/src/components/MarkdownEditor/index.spec.tsx
index 1aaa67f0ef..ad74740407 100644
--- a/src/frontend/packages/lib_markdown/src/components/MarkdownEditor/index.spec.tsx
+++ b/src/frontend/packages/lib_markdown/src/components/MarkdownEditor/index.spec.tsx
@@ -555,7 +555,7 @@ describe('', () => {
// Drop an image
const markdownImageId = '5459a5b2-2f81-11ed-ab8f-47c92ec0ac16';
fetchMock.postOnce(
- `/api/markdown-images/`,
+ `/api/markdown-documents/1/markdown-images/`,
markdownImageMockFactory({
id: markdownImageId,
active_stamp: null,
@@ -566,7 +566,7 @@ describe('', () => {
}),
);
fetchMock.postOnce(
- `/api/markdown-images/${markdownImageId}/initiate-upload/`,
+ `/api/markdown-documents/1/markdown-images/${markdownImageId}/initiate-upload/`,
{
fields: {
key: 'foo',
@@ -593,7 +593,7 @@ describe('', () => {
// Image is uploaded
fetchMock.get(
- `/api/markdown-images/${markdownImageId}/`,
+ `/api/markdown-documents/1/markdown-images/${markdownImageId}/`,
markdownImageMockFactory({
id: markdownImageId,
is_ready_to_show: true,
diff --git a/src/frontend/packages/lib_markdown/src/components/MarkdownEditor/index.tsx b/src/frontend/packages/lib_markdown/src/components/MarkdownEditor/index.tsx
index 275adf1d18..16e7547066 100644
--- a/src/frontend/packages/lib_markdown/src/components/MarkdownEditor/index.tsx
+++ b/src/frontend/packages/lib_markdown/src/components/MarkdownEditor/index.tsx
@@ -125,7 +125,10 @@ export const MarkdownEditor = ({ markdownDocumentId }: MarkdownEditorProps) => {
);
};
- const { addImageUpload } = useImageUploadManager(onImageUploadFinished);
+ const { addImageUpload } = useImageUploadManager(
+ markdownDocumentId,
+ onImageUploadFinished,
+ );
// note: we don't want to fetch the markdown document regularly to prevent
// any editor update while the user has not saved her document.
diff --git a/src/frontend/packages/lib_markdown/src/components/MdxRenderer/index.spec.tsx b/src/frontend/packages/lib_markdown/src/components/MdxRenderer/index.spec.tsx
index 3d77fb25d0..7ae39b0c36 100644
--- a/src/frontend/packages/lib_markdown/src/components/MdxRenderer/index.spec.tsx
+++ b/src/frontend/packages/lib_markdown/src/components/MdxRenderer/index.spec.tsx
@@ -381,7 +381,7 @@ describe('', () => {
const markdownText = fs.readFileSync(file, { encoding: 'utf8' });
fetchMock.getOnce(
- '/api/markdown-images/981a52a2-7caf-49a5-bb36-1d8512152214/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/981a52a2-7caf-49a5-bb36-1d8512152214/`,
markdownImageMockFactory({
id: '981a52a2-7caf-49a5-bb36-1d8512152214',
url: 'https://s3.link/easy-to-find.png',
@@ -389,7 +389,7 @@ describe('', () => {
);
fetchMock.getOnce(
- '/api/markdown-images/066036cc-2dde-11ed-89f4-afcf72a20b4c/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/066036cc-2dde-11ed-89f4-afcf72a20b4c/`,
markdownImageMockFactory({
id: '066036cc-2dde-11ed-89f4-afcf72a20b4c',
url: null,
diff --git a/src/frontend/packages/lib_markdown/src/components/MdxRenderer/index.tsx b/src/frontend/packages/lib_markdown/src/components/MdxRenderer/index.tsx
index b4aa71d05a..c824071212 100644
--- a/src/frontend/packages/lib_markdown/src/components/MdxRenderer/index.tsx
+++ b/src/frontend/packages/lib_markdown/src/components/MdxRenderer/index.tsx
@@ -90,7 +90,10 @@ export const MdxRenderer = ({
remarkLatexPlugin(markdownDocumentId),
remarkMermaidPlugin,
remarkMath,
- remarkLocallyHostedImagePlugin(localImagesUrlCache.current),
+ remarkLocallyHostedImagePlugin(
+ markdownDocumentId,
+ localImagesUrlCache.current,
+ ),
];
const rehypePlugins: PluggableList = [
options?.useMathjax ? rehypeMathjax : rehypeKatex,
diff --git a/src/frontend/packages/lib_markdown/src/components/MdxRenderer/remarkLocallyHostedImagePlugin.tsx b/src/frontend/packages/lib_markdown/src/components/MdxRenderer/remarkLocallyHostedImagePlugin.tsx
index 03ea4a3ea9..aba6c03bef 100644
--- a/src/frontend/packages/lib_markdown/src/components/MdxRenderer/remarkLocallyHostedImagePlugin.tsx
+++ b/src/frontend/packages/lib_markdown/src/components/MdxRenderer/remarkLocallyHostedImagePlugin.tsx
@@ -11,6 +11,7 @@ import { fetchOneMarkdownImage } from '@lib-markdown/data/queries';
import { MarkdownImageCache } from './types';
const remarkLocallyHostedImagePlugin = (
+ markdownDocumentId: string,
localImagesUrlCache: MarkdownImageCache,
) => {
// `markdownDocumentId` is mandatory to allow API calls
@@ -41,7 +42,10 @@ const remarkLocallyHostedImagePlugin = (
}
if (image.url.startsWith('/uploaded/image/')) {
- const response = await fetchOneMarkdownImage(imageId);
+ const response = await fetchOneMarkdownImage(
+ markdownDocumentId,
+ imageId,
+ );
if (response.url) {
localImagesUrlCache[imageId] = {
url: response.url,
diff --git a/src/frontend/packages/lib_markdown/src/components/useImageUploadManager/index.spec.tsx b/src/frontend/packages/lib_markdown/src/components/useImageUploadManager/index.spec.tsx
index bb90e94e99..e0f26a8450 100644
--- a/src/frontend/packages/lib_markdown/src/components/useImageUploadManager/index.spec.tsx
+++ b/src/frontend/packages/lib_markdown/src/components/useImageUploadManager/index.spec.tsx
@@ -23,13 +23,17 @@ jest.mock('lib-components', () => ({
describe('useImageUploadManager', () => {
let getLatestUseImageUploadManagerHookValues: () => any = () => {};
let getLatestUseUploadManagerHookValues: () => any = () => {};
+ const markdownDocumentId = 'truc';
const onImageUploadFinished = jest.fn();
const TestComponent = () => {
const uploadManager = useUploadManager();
getLatestUseUploadManagerHookValues = () => uploadManager;
- const imageUploadManager = useImageUploadManager(onImageUploadFinished);
+ const imageUploadManager = useImageUploadManager(
+ markdownDocumentId,
+ onImageUploadFinished,
+ );
getLatestUseImageUploadManagerHookValues = () => imageUploadManager;
return null;
};
@@ -49,8 +53,8 @@ describe('useImageUploadManager', () => {
const initiateUploadDeferred = new Deferred();
- const mockcreateMarkdownImage = fetchMock.postOnce(
- `/api/markdown-images/`,
+ const mockCreateMarkdownImage = fetchMock.postOnce(
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/`,
markdownImageMockFactory({
id: objectId,
active_stamp: null,
@@ -62,7 +66,7 @@ describe('useImageUploadManager', () => {
);
const mockInitiateUpload = fetchMock.postOnce(
- `/api/markdown-images/${objectId}/initiate-upload/`,
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${objectId}/initiate-upload/`,
initiateUploadDeferred.promise,
);
@@ -93,15 +97,18 @@ describe('useImageUploadManager', () => {
file,
progress: 0,
status: UploadManagerStatus.INIT,
+ parentId: markdownDocumentId,
},
});
expect(
mockInitiateUpload.calls(
- `/api/markdown-images/${objectId}/initiate-upload/`,
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${objectId}/initiate-upload/`,
),
).toHaveLength(1);
expect(
- mockcreateMarkdownImage.calls(`/api/markdown-images/`),
+ mockCreateMarkdownImage.calls(
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/`,
+ ),
).toHaveLength(1);
}
{
@@ -122,6 +129,7 @@ describe('useImageUploadManager', () => {
file,
progress: 0,
status: UploadManagerStatus.UPLOADING,
+ parentId: markdownDocumentId,
},
});
expect(screen.getByRole('status')).toHaveTextContent('course.gif0%');
@@ -129,7 +137,7 @@ describe('useImageUploadManager', () => {
// When status will turn to SUCCESS the image polling will start
fetchMock.get(
- `/api/markdown-images/${objectId}/`,
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${objectId}/`,
markdownImageMockFactory({
id: objectId,
is_ready_to_show: false,
@@ -152,6 +160,7 @@ describe('useImageUploadManager', () => {
file,
progress: 0,
status: UploadManagerStatus.SUCCESS,
+ parentId: markdownDocumentId,
},
});
expect(screen.getByRole('status')).toHaveTextContent(
@@ -162,7 +171,7 @@ describe('useImageUploadManager', () => {
{
act(() => {
fetchMock.get(
- `/api/markdown-images/${objectId}/`,
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${objectId}/`,
markdownImageMockFactory({
id: objectId,
is_ready_to_show: true,
diff --git a/src/frontend/packages/lib_markdown/src/components/useImageUploadManager/index.tsx b/src/frontend/packages/lib_markdown/src/components/useImageUploadManager/index.tsx
index 8a1f04d203..8ac5c67909 100644
--- a/src/frontend/packages/lib_markdown/src/components/useImageUploadManager/index.tsx
+++ b/src/frontend/packages/lib_markdown/src/components/useImageUploadManager/index.tsx
@@ -1,4 +1,5 @@
import {
+ MarkdownDocument,
UploadManagerStatus,
MarkdownDocumentModelName as modelName,
useUploadManager,
@@ -33,6 +34,7 @@ const toasterStyle = {
};
export const useImageUploadManager = (
+ markdownDocumentId: MarkdownDocument['id'],
onImageUploadFinished: (imageId: string, imageFileName: string) => void,
) => {
const intl = useIntl();
@@ -55,7 +57,7 @@ export const useImageUploadManager = (
// Once the update is done, the file will be processed, we have to wait for the processing
// to be done too, hence the polling.
await toast.promise(
- pollForMarkdownImage(imageId),
+ pollForMarkdownImage(markdownDocumentId, imageId),
{
loading: intl.formatMessage(messages.processing, {
imageName: uploadingObject.file.name,
@@ -83,16 +85,27 @@ export const useImageUploadManager = (
resetUpload(imageId);
}
});
- }, [intl, onImageUploadFinished, resetUpload, uploadManagerState]);
+ }, [
+ intl,
+ markdownDocumentId,
+ onImageUploadFinished,
+ resetUpload,
+ uploadManagerState,
+ ]);
const addImageUpload = useCallback(
async (file: File) => {
- const response = await createMarkdownImage();
+ const response = await createMarkdownImage(markdownDocumentId);
const markdownImageId = response.id;
- addUpload(modelName.MARKDOWN_IMAGES, markdownImageId, file);
+ addUpload(
+ modelName.MARKDOWN_IMAGES,
+ markdownImageId,
+ file,
+ markdownDocumentId,
+ );
return markdownImageId;
},
- [addUpload],
+ [addUpload, markdownDocumentId],
);
return { addImageUpload };
diff --git a/src/frontend/packages/lib_markdown/src/data/queries/index.tsx b/src/frontend/packages/lib_markdown/src/data/queries/index.tsx
index 3463bf7321..6f76f840fe 100644
--- a/src/frontend/packages/lib_markdown/src/data/queries/index.tsx
+++ b/src/frontend/packages/lib_markdown/src/data/queries/index.tsx
@@ -8,6 +8,7 @@ import {
} from '@tanstack/react-query';
import {
MarkdownDocument,
+ MarkdownImage,
MarkdownSaveTranslationsRequest,
MarkdownSaveTranslationsResponse,
actionOne,
@@ -212,10 +213,16 @@ export const markdownRenderLatex = (
};
// It has to be called outside hook context
-export const fetchOneMarkdownImage = (markdownImageId: string): any => {
+export const fetchOneMarkdownImage = (
+ markdownDocumentId: MarkdownDocument['id'],
+ markdownImageId: MarkdownImage['id'],
+): any => {
return fetchOne({
meta: undefined,
pageParam: undefined,
- queryKey: ['markdown-images', markdownImageId],
+ queryKey: [
+ `markdown-documents/${markdownDocumentId}/markdown-images`,
+ markdownImageId,
+ ],
});
};
diff --git a/src/frontend/packages/lib_markdown/src/data/sideEffects/createMarkdownImage/index.spec.tsx b/src/frontend/packages/lib_markdown/src/data/sideEffects/createMarkdownImage/index.spec.tsx
index bc17d7b4e4..a008009193 100644
--- a/src/frontend/packages/lib_markdown/src/data/sideEffects/createMarkdownImage/index.spec.tsx
+++ b/src/frontend/packages/lib_markdown/src/data/sideEffects/createMarkdownImage/index.spec.tsx
@@ -1,9 +1,11 @@
import fetchMock from 'fetch-mock';
import { useJwt } from 'lib-components';
+import { v4 as uuidv4 } from 'uuid';
import { createMarkdownImage } from './index';
describe('createMarkdownImage', () => {
+ const markdownDocumentId = uuidv4();
beforeEach(() => {
useJwt.setState({
jwt: 'token',
@@ -13,17 +15,20 @@ describe('createMarkdownImage', () => {
afterEach(() => fetchMock.restore());
it('creates a new shared live media and returns it', async () => {
- fetchMock.mock('/api/markdown-images/', {
- active_stamp: null,
- filename: null,
- id: '5570eb90-764e-4300-b92e-d3426e9046d2',
- is_ready_to_show: false,
- upload_state: 'pending',
- url: null,
- markdown_document: '72f53735-3283-456c-a562-4e1b59e2a686',
- });
+ fetchMock.mock(
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/`,
+ {
+ active_stamp: null,
+ filename: null,
+ id: '5570eb90-764e-4300-b92e-d3426e9046d2',
+ is_ready_to_show: false,
+ upload_state: 'pending',
+ url: null,
+ markdown_document: markdownDocumentId,
+ },
+ );
- const markdownImage = await createMarkdownImage();
+ const markdownImage = await createMarkdownImage(markdownDocumentId);
const fetchArgs = fetchMock.lastCall()![1]!;
@@ -34,7 +39,7 @@ describe('createMarkdownImage', () => {
is_ready_to_show: false,
upload_state: 'pending',
url: null,
- markdown_document: '72f53735-3283-456c-a562-4e1b59e2a686',
+ markdown_document: markdownDocumentId,
});
expect(fetchArgs.headers).toEqual({
Authorization: 'Bearer token',
@@ -45,19 +50,22 @@ describe('createMarkdownImage', () => {
it('throws when it fails to create the Markdown image (request failure)', async () => {
fetchMock.mock(
- '/api/markdown-images/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/`,
Promise.reject(new Error('Failed to perform the request')),
);
- await expect(createMarkdownImage()).rejects.toThrow(
+ await expect(createMarkdownImage(markdownDocumentId)).rejects.toThrow(
'Failed to perform the request',
);
});
it('throws when it fails to create the Markdown image (API error)', async () => {
- fetchMock.mock('/api/markdown-images/', 400);
+ fetchMock.mock(
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/`,
+ 400,
+ );
- await expect(createMarkdownImage()).rejects.toThrow(
+ await expect(createMarkdownImage(markdownDocumentId)).rejects.toThrow(
'Failed to create a new markdown image.',
);
});
diff --git a/src/frontend/packages/lib_markdown/src/data/sideEffects/createMarkdownImage/index.ts b/src/frontend/packages/lib_markdown/src/data/sideEffects/createMarkdownImage/index.ts
index 7d19d3ae7f..17dd79a75d 100644
--- a/src/frontend/packages/lib_markdown/src/data/sideEffects/createMarkdownImage/index.ts
+++ b/src/frontend/packages/lib_markdown/src/data/sideEffects/createMarkdownImage/index.ts
@@ -2,15 +2,18 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import {
API_ENDPOINT,
+ MarkdownDocument,
MarkdownImage,
fetchWrapper,
MarkdownDocumentModelName as modelName,
useJwt,
} from 'lib-components';
-export const createMarkdownImage = async () => {
+export const createMarkdownImage = async (
+ markdownDocumentId: MarkdownDocument['id'],
+) => {
const response = await fetchWrapper(
- `${API_ENDPOINT}/${modelName.MARKDOWN_IMAGES}/`,
+ `${API_ENDPOINT}/${modelName.MARKDOWN_DOCUMENTS}/${markdownDocumentId}/${modelName.MARKDOWN_IMAGES}/`,
{
headers: {
Authorization: `Bearer ${useJwt.getState().getJwt()}`,
diff --git a/src/frontend/packages/lib_markdown/src/data/sideEffects/pollForMarkdownImage/index.spec.tsx b/src/frontend/packages/lib_markdown/src/data/sideEffects/pollForMarkdownImage/index.spec.tsx
index 4c22cce959..0500208fc1 100644
--- a/src/frontend/packages/lib_markdown/src/data/sideEffects/pollForMarkdownImage/index.spec.tsx
+++ b/src/frontend/packages/lib_markdown/src/data/sideEffects/pollForMarkdownImage/index.spec.tsx
@@ -2,6 +2,7 @@ import { waitFor } from '@testing-library/react';
import fetchMock from 'fetch-mock';
import { markdownImageMockFactory } from 'index';
import { report } from 'lib-components';
+import { v4 as uuidv4 } from 'uuid';
import { pollForMarkdownImage } from './index';
@@ -10,6 +11,9 @@ jest.mock('lib-components', () => ({
report: jest.fn(),
}));
+const markdownDocumentId = uuidv4();
+const markdownImageId = uuidv4();
+
describe('pollForMarkdownImage', () => {
beforeEach(() => {
jest.clearAllMocks();
@@ -22,10 +26,10 @@ describe('pollForMarkdownImage', () => {
it('polls the image, backing off until it is ready and resolves with a success', async () => {
fetchMock.mock(
- '/api/markdown-images/c43f0c8f-4d3b-4219-86c3-86367b2b88cc/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${markdownImageId}/`,
JSON.stringify(
markdownImageMockFactory({
- id: 'c43f0c8f-4d3b-4219-86c3-86367b2b88cc',
+ id: markdownImageId,
is_ready_to_show: false,
}),
),
@@ -33,14 +37,15 @@ describe('pollForMarkdownImage', () => {
);
const promise = pollForMarkdownImage(
- 'c43f0c8f-4d3b-4219-86c3-86367b2b88cc',
+ markdownDocumentId,
+ markdownImageId,
1,
);
await waitFor(() => {
expect(
fetchMock.calls(
- '/api/markdown-images/c43f0c8f-4d3b-4219-86c3-86367b2b88cc/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${markdownImageId}/`,
{
method: 'GET',
},
@@ -49,11 +54,11 @@ describe('pollForMarkdownImage', () => {
});
const markdownImage = markdownImageMockFactory({
- id: 'c43f0c8f-4d3b-4219-86c3-86367b2b88cc',
+ id: markdownImageId,
is_ready_to_show: true,
});
fetchMock.mock(
- '/api/markdown-images/c43f0c8f-4d3b-4219-86c3-86367b2b88cc/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${markdownImageId}/`,
JSON.stringify(markdownImage),
{
method: 'GET',
@@ -64,7 +69,7 @@ describe('pollForMarkdownImage', () => {
await waitFor(() => {
expect(
fetchMock.calls(
- '/api/markdown-images/c43f0c8f-4d3b-4219-86c3-86367b2b88cc/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${markdownImageId}/`,
{
method: 'GET',
},
@@ -77,26 +82,26 @@ describe('pollForMarkdownImage', () => {
it('polls non-existing image', async () => {
fetchMock.mock(
- '/api/markdown-images/c43f0c8f-4d3b-4219-86c3-86367b2b88cc/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${markdownImageId}/`,
404,
{ method: 'GET' },
);
await expect(async () => {
- await pollForMarkdownImage('c43f0c8f-4d3b-4219-86c3-86367b2b88cc');
+ await pollForMarkdownImage(markdownDocumentId, markdownImageId);
}).rejects.toThrow(
- 'Failed to get /api/markdown-images/c43f0c8f-4d3b-4219-86c3-86367b2b88cc/.',
+ `Failed to get /api/markdown-documents/${markdownDocumentId}/markdown-images/${markdownImageId}/.`,
);
expect(report).toHaveBeenCalledWith(
Error(
- 'Failed to get /api/markdown-images/c43f0c8f-4d3b-4219-86c3-86367b2b88cc/.',
+ `Failed to get /api/markdown-documents/${markdownDocumentId}/markdown-images/${markdownImageId}/.`,
),
);
});
it('resolves with a failure and reports it when it fails to poll the image', async () => {
fetchMock.mock(
- '/api/markdown-images/15cf570a-5dc6-421a-9856-59e1b008a6fb/',
+ `/api/markdown-documents/${markdownDocumentId}/markdown-images/${markdownImageId}/`,
Promise.reject(new Error('Failed to get the image')),
{
method: 'GET',
@@ -105,7 +110,7 @@ describe('pollForMarkdownImage', () => {
);
await expect(async () => {
- await pollForMarkdownImage('15cf570a-5dc6-421a-9856-59e1b008a6fb');
+ await pollForMarkdownImage(markdownDocumentId, markdownImageId);
}).rejects.toThrow('Failed to get the image');
expect(report).toHaveBeenCalledWith(Error('Failed to get the image'));
diff --git a/src/frontend/packages/lib_markdown/src/data/sideEffects/pollForMarkdownImage/index.tsx b/src/frontend/packages/lib_markdown/src/data/sideEffects/pollForMarkdownImage/index.tsx
index a529c35e4e..c04d675a50 100644
--- a/src/frontend/packages/lib_markdown/src/data/sideEffects/pollForMarkdownImage/index.tsx
+++ b/src/frontend/packages/lib_markdown/src/data/sideEffects/pollForMarkdownImage/index.tsx
@@ -6,12 +6,13 @@ import { MarkdownImage, report } from 'lib-components';
import { fetchOneMarkdownImage } from '@lib-markdown/data/queries';
export async function pollForMarkdownImage(
- resourceId: string,
+ documentId: string,
+ imageId: string,
timer = 15,
counter = 1,
): Promise {
try {
- const image = await fetchOneMarkdownImage(resourceId);
+ const image = await fetchOneMarkdownImage(documentId, imageId);
if (image.is_ready_to_show) {
return image;
@@ -19,7 +20,7 @@ export async function pollForMarkdownImage(
counter++;
timer = timer * counter;
await new Promise((resolve) => window.setTimeout(resolve, 100 * timer));
- return await pollForMarkdownImage(resourceId, timer, counter);
+ return await pollForMarkdownImage(documentId, imageId, timer, counter);
}
} catch (error) {
report(error);