feat: enable problem bank button functionality on unit page (#1480)

This commit is contained in:
Navin Karkera
2024-11-15 01:30:23 +05:30
committed by GitHub
parent 033acc45f1
commit cee88885d9
17 changed files with 230 additions and 96 deletions

View File

@@ -282,7 +282,7 @@ describe('<CourseUnit />', () => {
await waitFor(() => {
const problemButton = getByRole('button', {
name: new RegExp(`${addComponentMessages.buttonText.defaultMessage} Problem`, 'i'),
name: new RegExp(`problem ${addComponentMessages.buttonText.defaultMessage} Problem`, 'i'),
});
userEvent.click(problemButton);

View File

@@ -82,6 +82,7 @@ module.exports = {
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: false,
},
{
type: 'discussion',
@@ -101,6 +102,7 @@ module.exports = {
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: false,
},
{
type: 'library',
@@ -114,12 +116,13 @@ module.exports = {
support_level: true,
},
],
display_name: 'Library Content',
display_name: 'Legacy Library Content',
support_legend: {
show_legend: false,
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: false,
},
{
type: 'html',
@@ -179,6 +182,7 @@ module.exports = {
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: false,
},
{
type: 'openassessment',
@@ -230,6 +234,7 @@ module.exports = {
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: false,
},
{
type: 'problem',
@@ -249,6 +254,7 @@ module.exports = {
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: false,
},
{
type: 'video',
@@ -268,6 +274,7 @@ module.exports = {
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: false,
},
{
type: 'drag-and-drop-v2',
@@ -287,6 +294,47 @@ module.exports = {
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: false,
},
{
type: 'library_v2',
templates: [
{
display_name: 'Library Content',
category: 'library_v2',
boilerplate_name: null,
hinted: false,
tab: 'advanced',
support_level: true,
},
],
display_name: 'Library Content',
support_legend: {
show_legend: false,
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: true,
},
{
type: 'itembank',
templates: [
{
display_name: 'Problem Bank',
category: 'itembank',
boilerplate_name: null,
hinted: false,
tab: 'advanced',
support_level: true,
},
],
display_name: 'Problem Bank',
support_legend: {
show_legend: false,
allow_unsupported_xblocks: false,
documentation_label: 'Your Platform Name Here Support Levels:',
},
beta: true,
},
],
course_sequence_ids: [

View File

@@ -2,13 +2,14 @@ import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useToggle } from '@openedx/paragon';
import { StandardModal, useToggle } from '@openedx/paragon';
import { getCourseSectionVertical } from '../data/selectors';
import { COMPONENT_TYPES } from '../../generic/block-type-utils/constants';
import ComponentModalView from './add-component-modals/ComponentModalView';
import AddComponentButton from './add-component-btn';
import messages from './messages';
import { ComponentPicker } from '../../library-authoring/component-picker';
const AddComponent = ({ blockId, handleCreateNewCourseXBlock }) => {
const navigate = useNavigate();
@@ -17,6 +18,17 @@ const AddComponent = ({ blockId, handleCreateNewCourseXBlock }) => {
const [isOpenHtml, openHtml, closeHtml] = useToggle(false);
const [isOpenOpenAssessment, openOpenAssessment, closeOpenAssessment] = useToggle(false);
const { componentTemplates } = useSelector(getCourseSectionVertical);
const [isAddLibraryContentModalOpen, showAddLibraryContentModal, closeAddLibraryContentModal] = useToggle();
const handleLibraryV2Selection = (selection) => {
handleCreateNewCourseXBlock({
type: COMPONENT_TYPES.libraryV2,
category: selection.blockType,
parentLocator: blockId,
libraryContentKey: selection.usageKey,
});
closeAddLibraryContentModal();
};
const handleCreateNewXBlock = (type, moduleName) => {
switch (type) {
@@ -35,6 +47,12 @@ const AddComponent = ({ blockId, handleCreateNewCourseXBlock }) => {
case COMPONENT_TYPES.library:
handleCreateNewCourseXBlock({ type, category: 'library_content', parentLocator: blockId });
break;
case COMPONENT_TYPES.itembank:
handleCreateNewCourseXBlock({ type, category: 'itembank', parentLocator: blockId });
break;
case COMPONENT_TYPES.libraryV2:
showAddLibraryContentModal();
break;
case COMPONENT_TYPES.advanced:
handleCreateNewCourseXBlock({
type: moduleName, category: moduleName, parentLocator: blockId,
@@ -67,7 +85,7 @@ const AddComponent = ({ blockId, handleCreateNewCourseXBlock }) => {
<h5 className="h3 mb-4 text-center">{intl.formatMessage(messages.title)}</h5>
<ul className="new-component-type list-unstyled m-0 d-flex flex-wrap justify-content-center">
{componentTemplates.map((component) => {
const { type, displayName } = component;
const { type, displayName, beta } = component;
let modalParams;
if (!component.templates.length) {
@@ -103,6 +121,7 @@ const AddComponent = ({ blockId, handleCreateNewCourseXBlock }) => {
onClick={() => handleCreateNewXBlock(type)}
displayName={displayName}
type={type}
beta={beta}
/>
</li>
);
@@ -118,6 +137,18 @@ const AddComponent = ({ blockId, handleCreateNewCourseXBlock }) => {
);
})}
</ul>
<StandardModal
title="Select component"
isOpen={isAddLibraryContentModalOpen}
onClose={closeAddLibraryContentModal}
isOverflowVisible={false}
size="xl"
>
<ComponentPicker
showOnlyPublished
onComponentSelected={handleLibraryV2Selection}
/>
</StandardModal>
</div>
);
};

View File

@@ -23,6 +23,11 @@ let axiosMock;
const blockId = '123';
const handleCreateNewCourseXBlockMock = jest.fn();
// Mock ComponentPicker to call onComponentSelected on load
jest.mock('../../library-authoring/component-picker', () => ({
ComponentPicker: (props) => props.onComponentSelected({ usageKey: 'test-usage-key', blockType: 'html' }),
}));
const renderComponent = (props) => render(
<AppProvider store={store}>
<IntlProvider locale="en">
@@ -59,11 +64,19 @@ describe('<AddComponent />', () => {
const componentTemplates = courseSectionVerticalMock.component_templates;
expect(getByRole('heading', { name: messages.title.defaultMessage })).toBeInTheDocument();
Object.keys(componentTemplates).map((component) => (
expect(getByRole('button', {
name: new RegExp(`${messages.buttonText.defaultMessage} ${componentTemplates[component].display_name}`, 'i'),
})).toBeInTheDocument()
));
Object.keys(componentTemplates).forEach((component) => {
const btn = getByRole('button', {
name: new RegExp(
`${componentTemplates[component].type
} ${messages.buttonText.defaultMessage} ${componentTemplates[component].display_name}`,
'i',
),
});
expect(btn).toBeInTheDocument();
if (component.beta) {
expect(within(btn).queryByText('Beta')).toBeInTheDocument();
}
});
});
it('AddComponent component doesn\'t render when there aren\'t componentTemplates', async () => {
@@ -111,7 +124,11 @@ describe('<AddComponent />', () => {
}
return expect(getByRole('button', {
name: new RegExp(`${messages.buttonText.defaultMessage} ${componentTemplates[component].display_name}`, 'i'),
name: new RegExp(
`${componentTemplates[component].type
} ${messages.buttonText.defaultMessage} ${componentTemplates[component].display_name}`,
'i',
),
})).toBeInTheDocument();
});
});
@@ -176,7 +193,7 @@ describe('<AddComponent />', () => {
const { getByRole } = renderComponent();
const discussionButton = getByRole('button', {
name: new RegExp(`${messages.buttonText.defaultMessage} Problem`, 'i'),
name: new RegExp(`problem ${messages.buttonText.defaultMessage} Problem`, 'i'),
});
userEvent.click(discussionButton);
@@ -187,6 +204,22 @@ describe('<AddComponent />', () => {
}, expect.any(Function));
});
it('calls handleCreateNewCourseXBlock with correct parameters when Problem bank xblock create button is clicked', () => {
const { getByRole } = renderComponent();
const problemBankBtn = getByRole('button', {
name: new RegExp(`${messages.buttonText.defaultMessage} Problem Bank`, 'i'),
});
userEvent.click(problemBankBtn);
expect(handleCreateNewCourseXBlockMock).toHaveBeenCalled();
expect(handleCreateNewCourseXBlockMock).toHaveBeenCalledWith({
parentLocator: '123',
type: COMPONENT_TYPES.itembank,
category: 'itembank',
});
});
it('calls handleCreateNewCourseXBlock with correct parameters when Video xblock create button is clicked', () => {
const { getByRole } = renderComponent();
@@ -206,7 +239,7 @@ describe('<AddComponent />', () => {
const { getByRole } = renderComponent();
const libraryButton = getByRole('button', {
name: new RegExp(`${messages.buttonText.defaultMessage} Library Content`, 'i'),
name: new RegExp(`${messages.buttonText.defaultMessage} Legacy Library Content`, 'i'),
});
userEvent.click(libraryButton);
@@ -379,6 +412,22 @@ describe('<AddComponent />', () => {
});
});
it('shows library picker on clicking v2 library content btn', async () => {
const { findByRole } = renderComponent();
const libBtn = await findByRole('button', {
name: new RegExp(`${messages.buttonText.defaultMessage} Library content`, 'i'),
});
userEvent.click(libBtn);
expect(handleCreateNewCourseXBlockMock).toHaveBeenCalled();
expect(handleCreateNewCourseXBlockMock).toHaveBeenCalledWith({
type: COMPONENT_TYPES.libraryV2,
parentLocator: '123',
category: 'html',
libraryContentKey: 'test-usage-key',
});
});
describe('component support label', () => {
it('component support label is hidden if component support legend is disabled', async () => {
const supportLevels = ['fs', 'ps'];

View File

@@ -1,11 +1,13 @@
import PropTypes from 'prop-types';
import { Button } from '@openedx/paragon';
import { Badge, Button } from '@openedx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from '../messages';
import AddComponentIcon from './AddComponentIcon';
const AddComponentButton = ({ type, displayName, onClick }) => {
const AddComponentButton = ({
type, displayName, onClick, beta,
}) => {
const intl = useIntl();
return (
@@ -17,14 +19,20 @@ const AddComponentButton = ({ type, displayName, onClick }) => {
<AddComponentIcon type={type} />
<span className="sr-only">{intl.formatMessage(messages.buttonText)}</span>
<span className="small mt-2">{displayName}</span>
{beta && <Badge className="pb-1 mt-1" variant="primary">Beta</Badge>}
</Button>
);
};
AddComponentButton.defaultProps = {
beta: false,
};
AddComponentButton.propTypes = {
type: PropTypes.string.isRequired,
displayName: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
beta: PropTypes.bool,
};
export default AddComponentButton;

View File

@@ -58,9 +58,11 @@ const ComponentModalView = ({
const isDisplaySupportLabel = supportLegend.showLegend && supportLabels[componentTemplate.supportLevel];
return (
<div className="d-flex justify-content-between w-100 mb-2.5 align-items-end">
<div
key={componentTemplate.displayName}
className="d-flex justify-content-between w-100 mb-2.5 align-items-end"
>
<Form.Radio
key={componentTemplate.displayName}
className="add-component-modal-radio"
value={value}
>

View File

@@ -63,9 +63,16 @@ export async function getCourseSectionVerticalData(unitId) {
* @param {string} [options.displayName] - The display name.
* @param {string} [options.boilerplate] - The boilerplate.
* @param {string} [options.stagedContent] - The staged content.
* @param {string} [options.libraryContentKey] - component key from library if being imported.
*/
export async function createCourseXblock({
type, category, parentLocator, displayName, boilerplate, stagedContent,
type,
category,
parentLocator,
displayName,
boilerplate,
stagedContent,
libraryContentKey,
}) {
const body = {
type,
@@ -74,6 +81,7 @@ export async function createCourseXblock({
parent_locator: parentLocator,
display_name: displayName,
staged_content: stagedContent,
library_content_key: libraryContentKey,
};
const { data } = await getAuthenticatedHttpClient()

View File

@@ -0,0 +1,17 @@
// This file will be no longer needed one https://github.com/openedx/paragon/pull/3045 is merged.
const NewsstandIcon = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
viewBox="0 -960 960 960"
{...props}
>
<path
d="M80-160v-80h800v80H80Zm80-160v-320h80v320h-80Zm160 0v-480h80v480h-80Zm160 0v-480h80v480h-80Zm280 0L600-600l70-40 160 280-70 40Z"
fill="currentColor"
/>
</svg>
);
export default NewsstandIcon;

View File

@@ -2,6 +2,7 @@ import React from 'react';
import {
BackHand as BackHandIcon,
BookOpen as BookOpenIcon,
Casino as ProblemBankIcon,
Edit as EditIcon,
EditNote as EditNoteIcon,
FormatListBulleted as FormatListBulletedIcon,
@@ -14,6 +15,7 @@ import {
VideoCamera as VideoCameraIcon,
Folder,
} from '@openedx/paragon/icons';
import NewsstandIcon from '../NewsstandIcon';
export const UNIT_ICON_TYPES = ['video', 'other', 'vertical', 'problem', 'lock'];
@@ -21,6 +23,8 @@ export const COMPONENT_TYPES = {
advanced: 'advanced',
discussion: 'discussion',
library: 'library',
libraryV2: 'library_v2',
itembank: 'itembank',
html: 'html',
openassessment: 'openassessment',
problem: 'problem',
@@ -40,6 +44,8 @@ export const COMPONENT_TYPE_ICON_MAP: Record<string, React.ComponentType> = {
[COMPONENT_TYPES.advanced]: ScienceIcon,
[COMPONENT_TYPES.discussion]: QuestionAnswerOutlineIcon,
[COMPONENT_TYPES.library]: LibraryIcon,
[COMPONENT_TYPES.itembank]: ProblemBankIcon,
[COMPONENT_TYPES.libraryV2]: NewsstandIcon,
[COMPONENT_TYPES.html]: TextFieldsIcon,
[COMPONENT_TYPES.openassessment]: EditNoteIcon,
[COMPONENT_TYPES.problem]: HelpOutlineIcon,

View File

@@ -10,7 +10,7 @@ import { LibraryProvider } from './common/context';
import { CreateCollectionModal } from './create-collection';
import { LibraryTeamModal } from './library-team';
import LibraryCollectionPage from './collections/LibraryCollectionPage';
import { ComponentPickerModal } from './component-picker';
import { ComponentPicker } from './component-picker';
import { ComponentEditorModal } from './components/ComponentEditorModal';
const LibraryLayout = () => {
@@ -32,9 +32,9 @@ const LibraryLayout = () => {
collectionId={collectionId}
/** The component picker modal to use. We need to pass it as a reference instead of
* directly importing it to avoid the import cycle:
* ComponentPickerModal > ComponentPicker > LibraryAuthoringPage/LibraryCollectionPage >
* Sidebar > AddContentContainer > ComponentPickerModal */
componentPickerModal={ComponentPickerModal}
* ComponentPicker > LibraryAuthoringPage/LibraryCollectionPage >
* Sidebar > AddContentContainer > ComponentPicker */
componentPicker={ComponentPicker}
>
<Routes>
<Route

View File

@@ -70,7 +70,7 @@ const AddContentContainer = () => {
collectionId,
openCreateCollectionModal,
openComponentEditor,
componentPickerModal,
componentPicker,
} = useLibraryContext();
const createBlockMutation = useCreateLibraryBlock();
const updateComponentsMutation = useAddComponentsToCollection(libraryId, collectionId);
@@ -235,7 +235,7 @@ const AddContentContainer = () => {
return (
<Stack direction="vertical">
{collectionId ? (
componentPickerModal && (
componentPicker && (
<>
<AddContentButton contentType={libraryContentButtonData} onCreateContent={onCreateContent} />
<PickLibraryContentModal

View File

@@ -10,7 +10,7 @@ import { studioHomeMock } from '../../studio-home/__mocks__';
import { getStudioHomeApiUrl } from '../../studio-home/data/api';
import mockResult from '../__mocks__/library-search.json';
import { LibraryProvider } from '../common/context';
import { ComponentPickerModal } from '../component-picker';
import { ComponentPicker } from '../component-picker';
import * as api from '../data/api';
import {
mockContentLibrary,
@@ -36,7 +36,7 @@ const render = () => baseRender(<PickLibraryContentModal isOpen onClose={onClose
<LibraryProvider
libraryId={libraryId}
collectionId="collectionId"
componentPickerModal={ComponentPickerModal}
componentPicker={ComponentPicker}
>
{children}
</LibraryProvider>

View File

@@ -1,6 +1,6 @@
import React, { useCallback, useContext, useState } from 'react';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { ActionRow, Button } from '@openedx/paragon';
import { ActionRow, Button, StandardModal } from '@openedx/paragon';
import { ToastContext } from '../../generic/toast-context';
import { type SelectedComponent, useLibraryContext } from '../common/context';
@@ -41,14 +41,14 @@ export const PickLibraryContentModal: React.FC<PickLibraryContentModalProps> = (
libraryId,
collectionId,
/** We need to get it as a reference instead of directly importing it to avoid the import cycle:
* ComponentPickerModal > ComponentPicker > LibraryAuthoringPage/LibraryCollectionPage >
* Sidebar > AddContentContainer > ComponentPickerModal */
componentPickerModal: ComponentPickerModal,
* ComponentPicker > LibraryAuthoringPage/LibraryCollectionPage >
* Sidebar > AddContentContainer > ComponentPicker */
componentPicker: ComponentPicker,
} = useLibraryContext();
// istanbul ignore if: this should never happen
if (!collectionId || !ComponentPickerModal) {
throw new Error('libraryId and componentPickerModal are required');
if (!collectionId || !ComponentPicker) {
throw new Error('libraryId and componentPicker are required');
}
const updateComponentsMutation = useAddComponentsToCollection(libraryId, collectionId);
@@ -70,12 +70,19 @@ export const PickLibraryContentModal: React.FC<PickLibraryContentModalProps> = (
}, [selectedComponents]);
return (
<ComponentPickerModal
libraryId={libraryId}
<StandardModal
title="Select components"
isOverflowVisible={false}
size="xl"
isOpen={isOpen}
onClose={onClose}
onChangeComponentSelection={setSelectedComponents}
footerNode={<PickLibraryContentModalFooter onSubmit={onSubmit} selectedComponents={selectedComponents} />}
/>
>
<ComponentPicker
libraryId={libraryId}
componentPickerMode="multiple"
onChangeComponentSelection={setSelectedComponents}
/>
</StandardModal>
);
};

View File

@@ -6,7 +6,7 @@ import React, {
useState,
} from 'react';
import type { ComponentPickerModal } from '../component-picker';
import type { ComponentPicker } from '../component-picker';
import type { ContentLibrary } from '../data/api';
import { useContentLibrary } from '../data/apiHooks';
@@ -27,9 +27,9 @@ type NoComponentPickerType = {
restrictToLibrary?: never;
/** The component picker modal to use. We need to pass it as a reference instead of
* directly importing it to avoid the import cycle:
* ComponentPickerModal > ComponentPicker > LibraryAuthoringPage/LibraryCollectionPage >
* Sidebar > AddContentContainer > ComponentPickerModal */
componentPickerModal?: typeof ComponentPickerModal;
* ComponentPicker > LibraryAuthoringPage/LibraryCollectionPage >
* Sidebar > AddContentContainer > ComponentPicker */
componentPicker?: typeof ComponentPicker;
};
type ComponentPickerSingleType = {
@@ -39,7 +39,7 @@ type ComponentPickerSingleType = {
addComponentToSelectedComponents?: never;
removeComponentFromSelectedComponents?: never;
restrictToLibrary: boolean;
componentPickerModal?: never;
componentPicker?: never;
};
type ComponentPickerMultipleType = {
@@ -49,7 +49,7 @@ type ComponentPickerMultipleType = {
addComponentToSelectedComponents: ComponentSelectedEvent;
removeComponentFromSelectedComponents: ComponentSelectedEvent;
restrictToLibrary: boolean;
componentPickerModal?: never;
componentPicker?: never;
};
type ComponentPickerType = NoComponentPickerType | ComponentPickerSingleType | ComponentPickerMultipleType;
@@ -127,7 +127,7 @@ type NoComponentPickerProps = {
onComponentSelected?: never;
onChangeComponentSelection?: never;
restrictToLibrary?: never;
componentPickerModal?: typeof ComponentPickerModal;
componentPicker?: typeof ComponentPicker;
};
export type ComponentPickerSingleProps = {
@@ -135,7 +135,7 @@ export type ComponentPickerSingleProps = {
onComponentSelected: ComponentSelectedEvent;
onChangeComponentSelection?: never;
restrictToLibrary?: boolean;
componentPickerModal?: never;
componentPicker?: never;
};
export type ComponentPickerMultipleProps = {
@@ -143,7 +143,7 @@ export type ComponentPickerMultipleProps = {
onComponentSelected?: never;
onChangeComponentSelection?: ComponentSelectionChangedEvent;
restrictToLibrary?: boolean;
componentPickerModal?: never;
componentPicker?: never;
};
type ComponentPickerProps = NoComponentPickerProps | ComponentPickerSingleProps | ComponentPickerMultipleProps;
@@ -156,7 +156,7 @@ type LibraryProviderProps = {
showOnlyPublished?: boolean;
/** Only used for testing */
initialSidebarComponentInfo?: SidebarComponentInfo;
componentPickerModal?: typeof ComponentPickerModal;
componentPicker?: typeof ComponentPicker;
} & ComponentPickerProps;
/**
@@ -172,7 +172,7 @@ export const LibraryProvider = ({
onChangeComponentSelection,
showOnlyPublished = false,
initialSidebarComponentInfo,
componentPickerModal,
componentPicker,
}: LibraryProviderProps) => {
const [collectionId, setCollectionId] = useState(collectionIdProp);
const [sidebarComponentInfo, setSidebarComponentInfo] = useState<SidebarComponentInfo | undefined>(
@@ -290,7 +290,7 @@ export const LibraryProvider = ({
if (!componentPickerMode) {
return {
...contextValue,
componentPickerModal,
componentPicker,
};
}
if (componentPickerMode === 'single') {
@@ -343,7 +343,7 @@ export const LibraryProvider = ({
openComponentEditor,
closeComponentEditor,
resetSidebarAdditionalActions,
componentPickerModal,
componentPicker,
]);
return (

View File

@@ -37,7 +37,7 @@ const defaultSelectionChangedCallback: ComponentSelectionChangedEvent = (selecti
window.parent.postMessage({ type: 'pickerSelectionChanged', selections }, '*');
};
type ComponentPickerProps = { libraryId?: string } & (
type ComponentPickerProps = { libraryId?: string, showOnlyPublished?: boolean } & (
{
componentPickerMode?: 'single',
onComponentSelected?: ComponentSelectedEvent,
@@ -53,6 +53,7 @@ type ComponentPickerProps = { libraryId?: string } & (
export const ComponentPicker: React.FC<ComponentPickerProps> = ({
/** Restrict the component picker to a specific library */
libraryId,
showOnlyPublished,
componentPickerMode = 'single',
/** This default callback is used to send the selected component back to the parent window,
* when the component picker is used in an iframe.
@@ -67,7 +68,7 @@ export const ComponentPicker: React.FC<ComponentPickerProps> = ({
const queryParams = new URLSearchParams(location.search);
const variant = queryParams.get('variant') || 'draft';
const showOnlyPublished = variant === 'published';
const calcShowOnlyPublished = variant === 'published' || showOnlyPublished;
const handleLibrarySelection = (library: string) => {
setCurrentStep('pick-components');
@@ -102,10 +103,10 @@ export const ComponentPicker: React.FC<ComponentPickerProps> = ({
<Stepper.Step eventKey="pick-components" title="Pick some components">
<LibraryProvider
libraryId={selectedLibrary}
showOnlyPublished={showOnlyPublished}
showOnlyPublished={calcShowOnlyPublished}
{...libraryProviderProps}
>
{ showOnlyPublished
{ calcShowOnlyPublished
&& (
<Alert variant="info" className="m-2">
<FormattedMessage {...messages.pickerInfoBanner} />

View File

@@ -1,43 +0,0 @@
import React from 'react';
import { StandardModal } from '@openedx/paragon';
import type { ComponentSelectionChangedEvent } from '../common/context';
import { ComponentPicker } from './ComponentPicker';
interface ComponentPickerModalProps {
libraryId?: string;
isOpen: boolean;
onClose: () => void;
onChangeComponentSelection: ComponentSelectionChangedEvent;
footerNode?: React.ReactNode;
}
// eslint-disable-next-line import/prefer-default-export
export const ComponentPickerModal: React.FC<ComponentPickerModalProps> = ({
libraryId,
isOpen,
onClose,
onChangeComponentSelection,
footerNode,
}) => {
if (!isOpen) {
return null;
}
return (
<StandardModal
title="Select components"
isOpen={isOpen}
onClose={onClose}
isOverflowVisible={false}
size="xl"
footerNode={footerNode}
>
<ComponentPicker
libraryId={libraryId}
componentPickerMode="multiple"
onChangeComponentSelection={onChangeComponentSelection}
/>
</StandardModal>
);
};

View File

@@ -1,2 +1,2 @@
/* eslint-disable import/prefer-default-export */
export { ComponentPicker } from './ComponentPicker';
export { ComponentPickerModal } from './ComponentPickerModal';