feat: course libraries review tab [FC-0076] (#1699)

Adds review tab to course libraries page. Also refactors all libraries page as per new designs.
This commit is contained in:
Navin Karkera
2025-03-12 17:58:27 +00:00
committed by GitHub
parent 3aa409d065
commit 77a55d9ad3
36 changed files with 1868 additions and 712 deletions

View File

@@ -8,7 +8,7 @@ import {
waitFor,
} from '../../testUtils';
import PreviewLibraryXBlockChanges, { LibraryChangesMessageData } from '.';
import IframePreviewLibraryXBlockChanges, { LibraryChangesMessageData } from '.';
import { messageTypes } from '../constants';
import { IframeProvider } from '../context/iFrameContext';
import { libraryBlockChangesUrl } from '../data/api';
@@ -31,7 +31,7 @@ jest.mock('../context/hooks', () => ({
}),
}));
const render = (eventData?: LibraryChangesMessageData) => {
baseRender(<PreviewLibraryXBlockChanges />, {
baseRender(<IframePreviewLibraryXBlockChanges />, {
extraWrapper: ({ children }) => <IframeProvider>{ children }</IframeProvider>,
});
const message = {
@@ -49,7 +49,7 @@ const render = (eventData?: LibraryChangesMessageData) => {
let axiosMock: MockAdapter;
let mockShowToast: (message: string, action?: ToastActionData | undefined) => void;
describe('<PreviewLibraryXBlockChanges />', () => {
describe('<IframePreviewLibraryXBlockChanges />', () => {
beforeEach(() => {
const mocks = initializeMocks();
axiosMock = mocks.axiosMock;

View File

@@ -1,4 +1,4 @@
import { useCallback, useContext, useState } from 'react';
import React, { useCallback, useContext, useState } from 'react';
import {
ActionRow, Button, ModalDialog, useToggle,
} from '@openedx/paragon';
@@ -24,36 +24,34 @@ export interface LibraryChangesMessageData {
isVertical: boolean,
}
const PreviewLibraryXBlockChanges = () => {
export interface PreviewLibraryXBlockChangesProps {
blockData?: LibraryChangesMessageData,
isModalOpen: boolean,
closeModal: () => void,
postChange: (accept: boolean) => void,
alertNode?: React.ReactNode,
}
/**
* Component to preview two xblock versions in a modal that depends on params
* to display blocks, open-close modal, accept-ignore changes and post change triggers
*/
export const PreviewLibraryXBlockChanges = ({
blockData,
isModalOpen,
closeModal,
postChange,
alertNode,
}: PreviewLibraryXBlockChangesProps) => {
const { showToast } = useContext(ToastContext);
const intl = useIntl();
const [blockData, setBlockData] = useState<LibraryChangesMessageData | undefined>(undefined);
// Main preview library modal toggle.
const [isModalOpen, openModal, closeModal] = useToggle(false);
// ignore changes confirmation modal toggle.
const [isConfirmModalOpen, openConfirmModal, closeConfirmModal] = useToggle(false);
const { data: componentMetadata } = useLibraryBlockMetadata(blockData?.upstreamBlockId);
const acceptChangesMutation = useAcceptLibraryBlockChanges();
const ignoreChangesMutation = useIgnoreLibraryBlockChanges();
const { data: componentMetadata } = useLibraryBlockMetadata(blockData?.upstreamBlockId);
const { sendMessageToIframe } = useIframe();
const receiveMessage = useCallback(({ data }: { data: {
payload: LibraryChangesMessageData;
type: string;
} }) => {
const { payload, type } = data;
if (type === messageTypes.showXBlockLibraryChangesPreview) {
setBlockData(payload);
openModal();
}
}, [openModal]);
useEventListener('message', receiveMessage);
const getTitle = useCallback(() => {
const oldName = blockData?.displayName;
@@ -95,7 +93,7 @@ const PreviewLibraryXBlockChanges = () => {
try {
await mutation.mutateAsync(blockData.downstreamBlockId);
sendMessageToIframe(messageTypes.refreshXBlock, null);
postChange(accept);
} catch (e) {
showToast(intl.formatMessage(failureMsg));
} finally {
@@ -112,6 +110,7 @@ const PreviewLibraryXBlockChanges = () => {
className="lib-preview-xblock-changes-modal"
hasCloseButton
isFullscreenOnMobile
isOverflowVisible={false}
>
<ModalDialog.Header>
<ModalDialog.Title>
@@ -119,6 +118,7 @@ const PreviewLibraryXBlockChanges = () => {
</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
{alertNode}
{getBody()}
</ModalDialog.Body>
<ModalDialog.Footer>
@@ -151,4 +151,42 @@ const PreviewLibraryXBlockChanges = () => {
);
};
export default PreviewLibraryXBlockChanges;
/**
* Wrapper over PreviewLibraryXBlockChanges to preview two xblock versions in a modal
* that depends on iframe message events to setBlockData and display modal.
*/
const IframePreviewLibraryXBlockChanges = () => {
const [blockData, setBlockData] = useState<LibraryChangesMessageData | undefined>(undefined);
// Main preview library modal toggle.
const [isModalOpen, openModal, closeModal] = useToggle(false);
const { sendMessageToIframe } = useIframe();
const receiveMessage = useCallback(({ data }: {
data: {
payload: LibraryChangesMessageData;
type: string;
}
}) => {
const { payload, type } = data;
if (type === messageTypes.showXBlockLibraryChangesPreview) {
setBlockData(payload);
openModal();
}
}, [openModal]);
useEventListener('message', receiveMessage);
return (
<PreviewLibraryXBlockChanges
blockData={blockData}
isModalOpen={isModalOpen}
closeModal={closeModal}
postChange={() => sendMessageToIframe(messageTypes.refreshXBlock, null)}
/>
);
};
export default IframePreviewLibraryXBlockChanges;