Skip to content

Commit 9c96a31

Browse files
committed
feat: [FC-0070] rendering library content in unit page
1 parent c917065 commit 9c96a31

33 files changed

+1433
-1248
lines changed

src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const COURSE_BLOCK_NAMES = ({
5858
chapter: { id: 'chapter', name: 'Section' },
5959
sequential: { id: 'sequential', name: 'Subsection' },
6060
vertical: { id: 'vertical', name: 'Unit' },
61+
libraryContent: { id: 'library_content', name: 'Library content' },
6162
component: { id: 'component', name: 'Component' },
6263
});
6364

src/course-team/CourseTeam.test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ describe('<CourseTeam />', () => {
189189
});
190190

191191
it('should delete user', async () => {
192-
`cleanup();`
192+
cleanup();
193193
axiosMock
194194
.onGet(getCourseTeamApiUrl(courseId))
195195
.reply(200, courseTeamMock);

src/course-unit/CourseUnit.jsx

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import ProcessingNotification from '../generic/processing-notification';
2222
import { SavingErrorAlert } from '../generic/saving-error-alert';
2323
import ConnectionErrorAlert from '../generic/ConnectionErrorAlert';
2424
import Loading from '../generic/Loading';
25+
import { COURSE_BLOCK_NAMES } from '../constants';
2526
import AddComponent from './add-component/AddComponent';
2627
import HeaderTitle from './header-title/HeaderTitle';
2728
import Breadcrumbs from './breadcrumbs/Breadcrumbs';
@@ -44,6 +45,7 @@ const CourseUnit = ({ courseId }) => {
4445
isLoading,
4546
sequenceId,
4647
unitTitle,
48+
unitCategory,
4749
errorMessage,
4850
sequenceStatus,
4951
savingStatus,
@@ -68,6 +70,19 @@ const CourseUnit = ({ courseId }) => {
6870
handleNavigateToTargetUnit,
6971
} = useCourseUnit({ courseId, blockId });
7072

73+
const isUnitVerticalType = unitCategory === COURSE_BLOCK_NAMES.vertical.id;
74+
const isUnitLibraryType = unitCategory === COURSE_BLOCK_NAMES.libraryContent.id;
75+
76+
const unitLayout = [{ span: 12 }, { span: 0 }];
77+
const defaultLayout = {
78+
lg: [{ span: 8 }, { span: 4 }],
79+
md: [{ span: 8 }, { span: 4 }],
80+
sm: [{ span: 8 }, { span: 3 }],
81+
xs: [{ span: 9 }, { span: 3 }],
82+
xl: [{ span: 9 }, { span: 3 }],
83+
};
84+
const layoutGrid = isUnitLibraryType ? { lg: unitLayout } : defaultLayout;
85+
7186
useEffect(() => {
7287
document.title = getPageHeadTitle('', unitTitle);
7388
}, [unitTitle]);
@@ -139,30 +154,30 @@ const CourseUnit = ({ courseId }) => {
139154
/>
140155
)}
141156
breadcrumbs={(
142-
<Breadcrumbs />
157+
<Breadcrumbs
158+
courseId={courseId}
159+
sequenceId={sequenceId}
160+
/>
143161
)}
144162
headerActions={(
145163
<HeaderNavigations
164+
unitCategory={unitCategory}
146165
headerNavigationsActions={headerNavigationsActions}
147166
/>
148167
)}
149168
/>
150-
<Sequence
151-
courseId={courseId}
152-
sequenceId={sequenceId}
153-
unitId={blockId}
154-
handleCreateNewCourseXBlock={handleCreateNewCourseXBlock}
155-
showPasteUnit={showPasteUnit}
156-
/>
157-
<Layout
158-
lg={[{ span: 8 }, { span: 4 }]}
159-
md={[{ span: 8 }, { span: 4 }]}
160-
sm={[{ span: 8 }, { span: 3 }]}
161-
xs={[{ span: 9 }, { span: 3 }]}
162-
xl={[{ span: 9 }, { span: 3 }]}
163-
>
169+
{isUnitVerticalType && (
170+
<Sequence
171+
courseId={courseId}
172+
sequenceId={sequenceId}
173+
unitId={blockId}
174+
handleCreateNewCourseXBlock={handleCreateNewCourseXBlock}
175+
showPasteUnit={showPasteUnit}
176+
/>
177+
)}
178+
<Layout {...layoutGrid}>
164179
<Layout.Element>
165-
{currentlyVisibleToStudents && (
180+
{!currentlyVisibleToStudents && (
166181
<AlertMessage
167182
className="course-unit__alert"
168183
title={intl.formatMessage(messages.alertUnpublishedVersion)}
@@ -177,11 +192,13 @@ const CourseUnit = ({ courseId }) => {
177192
/>
178193
)}
179194
<XBlockContainerIframe blockId={blockId} />
180-
<AddComponent
181-
blockId={blockId}
182-
handleCreateNewCourseXBlock={handleCreateNewCourseXBlock}
183-
/>
184-
{showPasteXBlock && canPasteComponent && (
195+
{isUnitVerticalType && (
196+
<AddComponent
197+
blockId={blockId}
198+
handleCreateNewCourseXBlock={handleCreateNewCourseXBlock}
199+
/>
200+
)}
201+
{showPasteXBlock && canPasteComponent && isUnitVerticalType && (
185202
<PasteComponent
186203
clipboardData={sharedClipboardData}
187204
onClick={handleCreateNewCourseXBlock}
@@ -197,18 +214,21 @@ const CourseUnit = ({ courseId }) => {
197214
</Layout.Element>
198215
<Layout.Element>
199216
<Stack gap={3}>
200-
<Sidebar data-testid="course-unit-sidebar">
201-
<PublishControls blockId={blockId} />
202-
</Sidebar>
203-
{getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true'
204-
&& (
205-
<Sidebar className="tags-sidebar">
206-
<TagsSidebarControls />
207-
</Sidebar>
217+
{isUnitVerticalType && (
218+
<>
219+
<Sidebar data-testid="course-unit-sidebar">
220+
<PublishControls blockId={blockId} />
221+
</Sidebar>
222+
{getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && (
223+
<Sidebar className="tags-sidebar">
224+
<TagsSidebarControls />
225+
</Sidebar>
226+
)}
227+
<Sidebar data-testid="course-unit-location-sidebar">
228+
<LocationInfo />
229+
</Sidebar>
230+
</>
208231
)}
209-
<Sidebar data-testid="course-unit-location-sidebar">
210-
<LocationInfo />
211-
</Sidebar>
212232
</Stack>
213233
</Layout.Element>
214234
</Layout>

src/course-unit/CourseUnit.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
@import "./header-title/HeaderTitle";
66
@import "./move-modal";
77

8+
.course-unit {
9+
min-width: 900px;
10+
}
11+
812
.course-unit__alert {
913
margin-bottom: 1.75rem;
1014
}

src/course-unit/CourseUnit.test.jsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import MockAdapter from 'axios-mock-adapter';
22
import {
3-
act, render, waitFor, fireEvent, within, screen,
3+
act, render, waitFor, fireEvent, within,
44
} from '@testing-library/react';
55
import userEvent from '@testing-library/user-event';
66
import { IntlProvider } from '@edx/frontend-platform/i18n';
@@ -803,7 +803,7 @@ describe('<CourseUnit />', () => {
803803
axiosMock
804804
.onPost(getXBlockBaseApiUrl(courseUnitIndexMock.id), {
805805
publish: null,
806-
metadata: { visible_to_staff_only: true, group_access: { 50: [2] } },
806+
metadata: { visible_to_staff_only: true, group_access: { 50: [2] }, discussion_enabled: true },
807807
})
808808
.reply(200, { dummy: 'value' });
809809
axiosMock
@@ -1145,8 +1145,8 @@ describe('<CourseUnit />', () => {
11451145
id: requestData.currentParentLocator,
11461146
category: 'vertical',
11471147
hasChildren: true,
1148-
}
1149-
}
1148+
},
1149+
},
11501150
},
11511151
origin: '*',
11521152
});
@@ -1169,7 +1169,7 @@ describe('<CourseUnit />', () => {
11691169
window.dispatchEvent(messageEvent);
11701170

11711171
expect(getByText(
1172-
moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', requestData.title)
1172+
moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', requestData.title),
11731173
)).toBeInTheDocument();
11741174
expect(getByRole('button', { name: moveModalMessages.moveModalSubmitButton.defaultMessage })).toBeInTheDocument();
11751175
expect(getByRole('button', { name: moveModalMessages.moveModalCancelButton.defaultMessage })).toBeInTheDocument();
@@ -1193,7 +1193,7 @@ describe('<CourseUnit />', () => {
11931193
window.dispatchEvent(messageEvent);
11941194

11951195
expect(getByText(
1196-
moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', requestData.title)
1196+
moveModalMessages.moveModalTitle.defaultMessage.replace('{displayName}', requestData.title),
11971197
)).toBeInTheDocument();
11981198

11991199
const currentSection = courseOutlineInfoMock.child_info.children[1];
@@ -1211,7 +1211,7 @@ describe('<CourseUnit />', () => {
12111211
fireEvent.click(currentSubsectionText);
12121212

12131213
const currentComponentLocationText = getByText(
1214-
moveModalMessages.moveModalOutlineItemCurrentComponentLocationText.defaultMessage
1214+
moveModalMessages.moveModalOutlineItemCurrentComponentLocationText.defaultMessage,
12151215
);
12161216
expect(currentComponentLocationText).toBeInTheDocument();
12171217
});

0 commit comments

Comments
 (0)