Skip to content

Commit aa908ef

Browse files
rpenidopomegranited
authored andcommitted
fix: several library unit page UX bugs (openedx#1868)
* fix: rename "Organize" tab to "Manage" * fix: duplicate key warnings * fix: uniform messages while adding to collection * fix: do not allow units be added to a unit (cherry picked from commit 0fdc460)
1 parent ab0e0d7 commit aa908ef

17 files changed

Lines changed: 88 additions & 64 deletions

src/library-authoring/LibraryAuthoringPage.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ describe('<LibraryAuthoringPage />', () => {
433433
const { getByRole, queryByText } = within(sidebar);
434434

435435
await waitFor(() => expect(queryByText(displayName)).toBeInTheDocument());
436-
expect(getByRole('tab', { selected: true })).toHaveTextContent('Organize');
436+
expect(getByRole('tab', { selected: true })).toHaveTextContent('Manage');
437437
const closeButton = getByRole('button', { name: /close/i });
438438
fireEvent.click(closeButton);
439439

src/library-authoring/add-content/AddContent.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ describe('<AddContent />', () => {
272272
await waitFor(() => expect(axiosMock.history.post[0].url).toEqual(pasteUrl));
273273
await waitFor(() => expect(axiosMock.history.patch.length).toEqual(1));
274274
await waitFor(() => expect(axiosMock.history.patch[0].url).toEqual(collectionComponentUrl));
275-
expect(mockShowToast).toHaveBeenCalledWith('There was an error linking the content to this collection.');
275+
expect(mockShowToast).toHaveBeenCalledWith('Failed to add content to collection.');
276276
});
277277

278278
it('should stop user from pasting unsupported blocks and show toast', async () => {

src/library-authoring/add-content/AddContent.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import { useLibraryContext } from '../common/context/LibraryContext';
2929
import { PickLibraryContentModal } from './PickLibraryContentModal';
3030
import { blockTypes } from '../../editors/data/constants/app';
3131

32+
import { ContentType as LibraryContentTypes } from '../routes';
33+
import genericMessages from '../generic/messages';
3234
import messages from './messages';
3335
import type { BlockTypeMetadata } from '../data/api';
3436
import { getContainerTypeFromId, ContainerType } from '../../generic/key-utils';
@@ -114,6 +116,9 @@ const AddContentView = ({
114116
blockType: 'libraryContent',
115117
};
116118

119+
const extraFilter = unitId ? ['NOT block_type = "unit"', 'NOT type = "collections"'] : undefined;
120+
const visibleTabs = unitId ? [LibraryContentTypes.components] : undefined;
121+
117122
return (
118123
<>
119124
{(collectionId || unitId) && componentPicker && (
@@ -123,6 +128,8 @@ const AddContentView = ({
123128
<PickLibraryContentModal
124129
isOpen={isAddLibraryContentModalOpen}
125130
onClose={closeAddLibraryContentModal}
131+
extraFilter={extraFilter}
132+
visibleTabs={visibleTabs}
126133
/>
127134
</>
128135
)}
@@ -301,7 +308,7 @@ const AddContent = () => {
301308
const linkComponent = (opaqueKey: string) => {
302309
if (collectionId) {
303310
addComponentsToCollectionMutation.mutateAsync([opaqueKey]).catch(() => {
304-
showToast(intl.formatMessage(messages.errorAssociateComponentToCollectionMessage));
311+
showToast(intl.formatMessage(genericMessages.manageCollectionsFailed));
305312
});
306313
}
307314
if (unitId) {

src/library-authoring/add-content/PickLibraryContentModal.test.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ describe('<PickLibraryContentModal />', () => {
9292
}
9393
});
9494
expect(onClose).toHaveBeenCalled();
95-
expect(mockShowToast).toHaveBeenCalledWith('Content linked successfully.');
95+
const text = context === 'collection'
96+
? 'Content added to collection.'
97+
: 'Content linked successfully.';
98+
expect(mockShowToast).toHaveBeenCalledWith(text);
9699
});
97100

98101
it(`show error when api call fails (${context})`, async () => {
@@ -130,8 +133,10 @@ describe('<PickLibraryContentModal />', () => {
130133
}
131134
});
132135
expect(onClose).toHaveBeenCalled();
133-
const name = context === 'collection' ? 'collection' : 'container';
134-
expect(mockShowToast).toHaveBeenCalledWith(`There was an error linking the content to this ${name}.`);
136+
const text = context === 'collection'
137+
? 'Failed to add content to collection.'
138+
: 'There was an error linking the content to this container.';
139+
expect(mockShowToast).toHaveBeenCalledWith(text);
135140
});
136141
});
137142
});

src/library-authoring/add-content/PickLibraryContentModal.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { ToastContext } from '../../generic/toast-context';
66
import { useLibraryContext } from '../common/context/LibraryContext';
77
import type { SelectedComponent } from '../common/context/ComponentPickerContext';
88
import { useAddItemsToCollection, useAddComponentsToContainer } from '../data/apiHooks';
9+
import genericMessages from '../generic/messages';
10+
import type { ContentType } from '../routes';
911
import messages from './messages';
1012

1113
interface PickLibraryContentModalFooterProps {
@@ -32,12 +34,14 @@ interface PickLibraryContentModalProps {
3234
isOpen: boolean;
3335
onClose: () => void;
3436
extraFilter?: string[];
37+
visibleTabs?: ContentType[],
3538
}
3639

3740
export const PickLibraryContentModal: React.FC<PickLibraryContentModalProps> = ({
3841
isOpen,
3942
onClose,
4043
extraFilter,
44+
visibleTabs,
4145
}) => {
4246
const intl = useIntl();
4347

@@ -69,16 +73,16 @@ export const PickLibraryContentModal: React.FC<PickLibraryContentModalProps> = (
6973
if (collectionId) {
7074
updateCollectionItemsMutation.mutateAsync(usageKeys)
7175
.then(() => {
72-
showToast(intl.formatMessage(messages.successAssociateComponentMessage));
76+
showToast(intl.formatMessage(genericMessages.manageCollectionsSuccess));
7377
})
7478
.catch(() => {
75-
showToast(intl.formatMessage(messages.errorAssociateComponentToCollectionMessage));
79+
showToast(intl.formatMessage(genericMessages.manageCollectionsFailed));
7680
});
7781
}
7882
if (unitId) {
7983
updateUnitComponentsMutation.mutateAsync(usageKeys)
8084
.then(() => {
81-
showToast(intl.formatMessage(messages.successAssociateComponentMessage));
85+
showToast(intl.formatMessage(messages.successAssociateComponentToContainerMessage));
8286
})
8387
.catch(() => {
8488
showToast(intl.formatMessage(messages.errorAssociateComponentToContainerMessage));
@@ -109,6 +113,7 @@ export const PickLibraryContentModal: React.FC<PickLibraryContentModalProps> = (
109113
componentPickerMode="multiple"
110114
onChangeComponentSelection={setSelectedComponents}
111115
extraFilter={extraFilter}
116+
visibleTabs={visibleTabs}
112117
/>
113118
</StandardModal>
114119
);

src/library-authoring/add-content/messages.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,10 @@ const messages = defineMessages({
8484
+ ' The {detail} text provides more information about the error.'
8585
),
8686
},
87-
successAssociateComponentMessage: {
88-
id: 'course-authoring.library-authoring.associate-collection-content.success.text',
87+
successAssociateComponentToContainerMessage: {
88+
id: 'course-authoring.library-authoring.associate-container-content.success.text',
8989
defaultMessage: 'Content linked successfully.',
90-
description: 'Message when linking of content to a collection in library is success',
91-
},
92-
errorAssociateComponentToCollectionMessage: {
93-
id: 'course-authoring.library-authoring.associate-collection-content.error.text',
94-
defaultMessage: 'There was an error linking the content to this collection.',
95-
description: 'Message when linking of content to a collection in library fails',
90+
description: 'Message when linking of content to a container in library is success',
9691
},
9792
errorAssociateComponentToContainerMessage: {
9893
id: 'course-authoring.library-authoring.associate-container-content.error.text',

src/library-authoring/common/context/SidebarContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const isComponentInfoTab = (tab: string): tab is ComponentInfoTab => (
3636

3737
export const UNIT_INFO_TABS = {
3838
Preview: 'preview',
39-
Organize: 'organize',
39+
Manage: 'manage',
4040
Usage: 'usage',
4141
Settings: 'settings',
4242
} as const;

src/library-authoring/components/ContainerCard.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ const ContainerCardPreview = ({ containerId, showMaxChildren = 5 }: ContainerCar
147147
}
148148
return (
149149
<div
150-
key={`container-card-preview-block-${id}`}
150+
// A container can have multiple instances of the same block
151+
// eslint-disable-next-line react/no-array-index-key
152+
key={`${id}-${idx}`}
151153
className={classNames}
152154
>
153155
{blockPreview}

src/library-authoring/containers/ContainerOrganize.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ const ContainerOrganize = () => {
8585
>
8686
<Stack gap={1} direction="horizontal">
8787
<Icon src={Tag} />
88-
{intl.formatMessage(messages.organizeTabTagsTitle, { count: tagsCount })}
88+
{intl.formatMessage(messages.manageTabTagsTitle, { count: tagsCount })}
8989
</Stack>
9090
<Collapsible.Visible whenClosed>
9191
<Icon src={ExpandMore} />
@@ -113,7 +113,7 @@ const ContainerOrganize = () => {
113113
>
114114
<Stack gap={1} direction="horizontal">
115115
<Icon src={BookOpen} />
116-
{intl.formatMessage(messages.organizeTabCollectionsTitle, { count: collectionsCount })}
116+
{intl.formatMessage(messages.manageTabCollectionsTitle, { count: collectionsCount })}
117117
</Stack>
118118
<Collapsible.Visible whenClosed>
119119
<Icon src={ExpandMore} />

src/library-authoring/containers/UnitInfo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ const UnitInfo = () => {
120120
useEffect(() => {
121121
// Show Organize tab if JumpToAddCollections action is set in sidebarComponentInfo
122122
if (jumpToCollections) {
123-
setSidebarTab(UNIT_INFO_TABS.Organize);
123+
setSidebarTab(UNIT_INFO_TABS.Manage);
124124
}
125125
}, [jumpToCollections, setSidebarTab]);
126126

@@ -166,7 +166,7 @@ const UnitInfo = () => {
166166
onSelect={setSidebarTab}
167167
>
168168
{renderTab(UNIT_INFO_TABS.Preview, <LibraryUnitBlocks preview />, intl.formatMessage(messages.previewTabTitle))}
169-
{renderTab(UNIT_INFO_TABS.Organize, <ContainerOrganize />, intl.formatMessage(messages.organizeTabTitle))}
169+
{renderTab(UNIT_INFO_TABS.Manage, <ContainerOrganize />, intl.formatMessage(messages.manageTabTitle))}
170170
{renderTab(UNIT_INFO_TABS.Settings, 'Unit Settings', intl.formatMessage(messages.settingsTabTitle))}
171171
</Tabs>
172172
</Stack>

0 commit comments

Comments
 (0)