Skip to content

Commit b027438

Browse files
committed
feat: Partial import for Import details page
1 parent 63ab799 commit b027438

File tree

7 files changed

+134
-8
lines changed

7 files changed

+134
-8
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ INVITE_STUDENTS_EMAIL_TO=''
4545
ENABLE_CHECKLIST_QUALITY=''
4646
ENABLE_GRADING_METHOD_IN_PROBLEMS=false
4747
# "Multi-level" blocks are unsupported in libraries
48-
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder"
48+
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,library_content,itembank"
4949
# Fallback in local style files
5050
PARAGON_THEME_URLS={}
5151
COURSE_TEAM_SUPPORT_EMAIL=''

.env.development

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ INVITE_STUDENTS_EMAIL_TO="[email protected]"
4848
ENABLE_CHECKLIST_QUALITY=true
4949
ENABLE_GRADING_METHOD_IN_PROBLEMS=false
5050
# "Multi-level" blocks are unsupported in libraries
51-
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,library_content"
51+
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,library_content,itembank"
5252
# Fallback in local style files
5353
PARAGON_THEME_URLS={}
5454
COURSE_TEAM_SUPPORT_EMAIL=''

.env.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ INVITE_STUDENTS_EMAIL_TO="[email protected]"
4040
ENABLE_CHECKLIST_QUALITY=true
4141
ENABLE_GRADING_METHOD_IN_PROBLEMS=false
4242
# "Multi-level" blocks are unsupported in libraries
43-
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder"
43+
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,library_content,itembank"
4444
PARAGON_THEME_URLS=
4545
COURSE_TEAM_SUPPORT_EMAIL='[email protected]'

src/data/api.mocks.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ mockGetMigrationStatus.migrationStatusData = {
4747
components: 0,
4848
unsupported: 0,
4949
},
50+
unsupportedReasons: [],
5051
},
5152
],
5253
} as api.MigrateTaskStatusData;
@@ -81,6 +82,7 @@ mockGetMigrationStatus.migrationStatusFailedData = {
8182
components: 0,
8283
unsupported: 0,
8384
},
85+
unsupportedReasons: [],
8486
},
8587
],
8688
} as api.MigrateTaskStatusData;
@@ -115,6 +117,7 @@ mockGetMigrationStatus.migrationStatusFailedMultipleData = {
115117
components: 0,
116118
unsupported: 0,
117119
},
120+
unsupportedReasons: [],
118121
},
119122
{
120123
id: 2,
@@ -135,6 +138,7 @@ mockGetMigrationStatus.migrationStatusFailedMultipleData = {
135138
components: 0,
136139
unsupported: 0,
137140
},
141+
unsupportedReasons: [],
138142
},
139143
],
140144
} as api.MigrateTaskStatusData;
@@ -169,6 +173,7 @@ mockGetMigrationStatus.migrationStatusFailedOneLibraryData = {
169173
components: 0,
170174
unsupported: 0,
171175
},
176+
unsupportedReasons: [],
172177
},
173178
{
174179
id: 2,
@@ -189,6 +194,7 @@ mockGetMigrationStatus.migrationStatusFailedOneLibraryData = {
189194
components: 0,
190195
unsupported: 0,
191196
},
197+
unsupportedReasons: [],
192198
},
193199
],
194200
} as api.MigrateTaskStatusData;

src/data/api.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ export interface MigrateParameters {
105105
components: number;
106106
unsupported: number;
107107
}
108+
unsupportedReasons: {
109+
block_name: string;
110+
block_type: string;
111+
reason: string;
112+
}[];
108113
}
109114

110115
export interface MigrateTaskStatusData {

src/library-authoring/import-course/ImportDetailsPage.tsx

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ import { useNavigate, useParams } from 'react-router';
44
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
55
import {
66
Stack, Container, Alert, Layout, Button,
7+
DataTable,
78
} from '@openedx/paragon';
89

910
import Header from '@src/header';
1011
import { useCourseDetails } from '@src/course-outline/data/apiHooks';
1112
import SubHeader from '@src/generic/sub-header/SubHeader';
12-
import { ArrowForward, CheckCircle, Info } from '@openedx/paragon/icons';
13+
import {
14+
ArrowForward, CheckCircle, Info, WarningFilled,
15+
} from '@openedx/paragon/icons';
1316
import Loading from '@src/generic/Loading';
1417
import { ToastContext } from '@src/generic/toast-context';
18+
import { Paragraph } from '@src/utils';
1519

1620
import { useBulkModulestoreMigrate, useModulestoreMigrationStatus } from '@src/data/apiHooks';
1721
import messages from './messages';
@@ -66,6 +70,8 @@ export const ImportDetailsPage = () => {
6670
// TODO: Update this code when using simple migration
6771
if (courseImportDetails?.isFailed) {
6872
migrationStatus = 'Failed';
73+
} else if (courseImportDetails?.migrationSummary.unsupported !== 0) {
74+
migrationStatus = 'Partial Succeeded';
6975
} else {
7076
migrationStatus = 'Succeeded';
7177
}
@@ -128,10 +134,10 @@ export const ImportDetailsPage = () => {
128134
</Alert>
129135
<h4><FormattedMessage {...messages.importSummaryTitle} /></h4>
130136
<SummaryCard
131-
totalBlocks={courseImportDetails.migrationSummary.totalBlocks}
132-
totalComponents={
133-
courseImportDetails.migrationSummary.components + courseImportDetails.migrationSummary.unsupported
137+
totalBlocks={
138+
courseImportDetails.migrationSummary.totalBlocks - courseImportDetails.migrationSummary.unsupported
134139
}
140+
totalComponents={courseImportDetails.migrationSummary.components}
135141
sections={courseImportDetails.migrationSummary.sections}
136142
subsections={courseImportDetails.migrationSummary.subsections}
137143
units={courseImportDetails.migrationSummary.units}
@@ -188,14 +194,90 @@ export const ImportDetailsPage = () => {
188194
</div>
189195
</Stack>
190196
);
197+
} if (migrationStatus === 'Partial Succeeded') {
198+
const importedSuccessfullyCount = courseImportDetails.migrationSummary.totalBlocks
199+
- courseImportDetails.migrationSummary.unsupported;
200+
201+
return (
202+
<Stack gap={3}>
203+
<Alert variant="warning" icon={WarningFilled}>
204+
<Alert.Heading>
205+
<FormattedMessage {...messages.importPartialAlertTitle} />
206+
</Alert.Heading>
207+
<p>
208+
<FormattedMessage
209+
{...messages.importPartialAlertBody}
210+
values={{
211+
courseName: courseDetails?.title,
212+
collectionName: courseImportDetails.targetCollection?.title,
213+
}}
214+
/>
215+
</p>
216+
</Alert>
217+
<h4><FormattedMessage {...messages.importSummaryTitle} /></h4>
218+
<SummaryCard
219+
totalBlocks={
220+
courseImportDetails.migrationSummary.totalBlocks - courseImportDetails.migrationSummary.unsupported
221+
}
222+
totalComponents={courseImportDetails.migrationSummary.components}
223+
sections={courseImportDetails.migrationSummary.sections}
224+
subsections={courseImportDetails.migrationSummary.subsections}
225+
units={courseImportDetails.migrationSummary.units}
226+
unsupportedBlocks={courseImportDetails.migrationSummary.unsupported}
227+
/>
228+
<div>
229+
<FormattedMessage
230+
{...messages.importPartialBody}
231+
values={{
232+
percentage: Math.floor(
233+
(importedSuccessfullyCount * 100) / courseImportDetails.migrationSummary.totalBlocks,
234+
),
235+
courseName: courseDetails?.title,
236+
p: Paragraph,
237+
}}
238+
/>
239+
</div>
240+
<DataTable
241+
columns={[
242+
{
243+
Header: intl.formatMessage(messages.importPartialReasonTableBlockName),
244+
accessor: 'blockName',
245+
246+
},
247+
{
248+
Header: intl.formatMessage(messages.importPartialReasonTableBlockType),
249+
accessor: 'blockType',
250+
},
251+
{
252+
Header: intl.formatMessage(messages.importPartialReasonTableReason),
253+
accessor: 'reason',
254+
},
255+
]}
256+
data={courseImportDetails.unsupportedReasons}
257+
>
258+
<DataTable.Table />
259+
</DataTable>
260+
<div className="w-100 d-flex justify-content-end">
261+
<Button
262+
variant="outline-primary"
263+
iconAfter={ArrowForward}
264+
onClick={() => navigate(collectionLink())}
265+
>
266+
<FormattedMessage {...messages.viewImportedContentButton} />
267+
</Button>
268+
</div>
269+
</Stack>
270+
);
191271
}
272+
192273
return (
193-
// In Progress
274+
// In Progress
194275
<Stack gap={3}>
195276
<h4><FormattedMessage {...messages.importInProgressTitle} /></h4>
196277
<p>
197278
<FormattedMessage {...messages.importInProgressBody} />
198279
</p>
280+
<h4><FormattedMessage {...messages.importSummaryTitle} /></h4>
199281
<SummaryCard isPending />
200282
<div className="w-100 d-flex justify-content-end">
201283
<Button

src/library-authoring/import-course/messages.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,39 @@ const messages = defineMessages({
280280
defaultMessage: 'Course {courseName} is being imported. This page will update when import is complete',
281281
description: 'Body of the import details when the migration is in progress',
282282
},
283+
importPartialAlertTitle: {
284+
id: 'library-authoring.import-course.import-details.import-partial.alert.title',
285+
defaultMessage: 'Partial Import Successful',
286+
description: 'Title of the alert in the import details page when the migration is in partial import.',
287+
},
288+
importPartialAlertBody: {
289+
id: 'library-authoring.import-course.import-details.import-partial.alert.title',
290+
defaultMessage: '{courseName} has been imported to your library in a collection called {collectionName}.'
291+
+ ' Some content was not added to your course. See details bellow.',
292+
description: 'Body of the alert in the import details page when the migration is in partial import.',
293+
},
294+
importPartialBody: {
295+
id: 'library-authoring.import-course.import-details.import-partial.alert.title',
296+
defaultMessage: '<p>{percentage}% of Course {courseName} has been imported successfully.'
297+
+ ' Imported Course content can be edited and remixed in your Library, and reused in Courses.</p>'
298+
+ '<p>Details of the import, including reasons some content was not abled to be imported are described below</p>',
299+
description: 'Body of the import details page when the migration is in partial import.',
300+
},
301+
importPartialReasonTableBlockName: {
302+
id: 'library-authoring.import-course.import-details.reasons-table.block-name',
303+
defaultMessage: 'Block Name',
304+
description: 'Label for the Block Name field in the Reasons table in the import details',
305+
},
306+
importPartialReasonTableBlockType: {
307+
id: 'library-authoring.import-course.import-details.reasons-table.block-type',
308+
defaultMessage: 'Block Type',
309+
description: 'Label for the Block Type field in the Reasons table in the import details',
310+
},
311+
importPartialReasonTableReason: {
312+
id: 'library-authoring.import-course.import-details.reasons-table.reason',
313+
defaultMessage: 'Reason For Failed import',
314+
description: 'Label for the Reason For Failed import field in the Reasons table in the import details',
315+
},
283316
});
284317

285318
export default messages;

0 commit comments

Comments
 (0)