Skip to content

Commit 7769d81

Browse files
committed
feat: Add slots for video and file upload components and alerts
This change add plugin slots for the file and video upload components, and the alerts components on those pages.
1 parent 39e5f89 commit 7769d81

17 files changed

Lines changed: 700 additions & 461 deletions

File tree

src/course-outline/page-alerts/PageAlerts.jsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,31 @@
1-
import React, { useState } from 'react';
2-
import PropTypes from 'prop-types';
3-
import { uniqBy } from 'lodash';
41
import { getConfig } from '@edx/frontend-platform';
5-
import { useDispatch, useSelector } from 'react-redux';
62
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
3+
import {
4+
Alert, Button, Hyperlink, Truncate,
5+
} from '@openedx/paragon';
76
import {
87
Campaign as CampaignIcon,
8+
Error as ErrorIcon,
99
InfoOutline as InfoOutlineIcon,
1010
Warning as WarningIcon,
11-
Error as ErrorIcon,
1211
} from '@openedx/paragon/icons';
13-
import {
14-
Alert, Button, Hyperlink, Truncate,
15-
} from '@openedx/paragon';
12+
import { uniqBy } from 'lodash';
13+
import PropTypes from 'prop-types';
14+
import React, { useState } from 'react';
15+
import { useDispatch, useSelector } from 'react-redux';
1616
import { Link, useNavigate } from 'react-router-dom';
17+
import CourseOutlinePageAlertsSlot from '../../plugin-slots/CourseOutlinePageAlertsSlot';
18+
import advancedSettingsMessages from '../../advanced-settings/messages';
19+
import { OutOfSyncAlert } from '../../course-libraries/OutOfSyncAlert';
20+
import { RequestStatus } from '../../data/constants';
1721

1822
import ErrorAlert from '../../editors/sharedComponents/ErrorAlerts/ErrorAlert';
19-
import { RequestStatus } from '../../data/constants';
2023
import AlertMessage from '../../generic/alert-message';
2124
import AlertProctoringError from '../../generic/AlertProctoringError';
22-
import messages from './messages';
23-
import advancedSettingsMessages from '../../advanced-settings/messages';
25+
import { API_ERROR_TYPES } from '../constants';
2426
import { getPasteFileNotices } from '../data/selectors';
2527
import { dismissError, removePasteFileNotices } from '../data/slice';
26-
import { API_ERROR_TYPES } from '../constants';
27-
import { OutOfSyncAlert } from '../../course-libraries/OutOfSyncAlert';
28+
import messages from './messages';
2829

2930
const PageAlerts = ({
3031
courseId,
@@ -437,6 +438,7 @@ const PageAlerts = ({
437438
{conflictingFilesPasteAlert()}
438439
{newFilesPasteAlert()}
439440
{renderOutOfSyncAlert()}
441+
<CourseOutlinePageAlertsSlot />
440442
</>
441443
);
442444
};

src/files-and-videos/files-page/FilesPage.jsx

Lines changed: 15 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,18 @@
1-
import React, { useEffect } from 'react';
1+
import { useIntl } from '@edx/frontend-platform/i18n';
2+
import { Container } from '@openedx/paragon';
23
import PropTypes from 'prop-types';
4+
import React, { useEffect } from 'react';
35
import { useDispatch, useSelector } from 'react-redux';
4-
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
5-
import { CheckboxFilter, Container } from '@openedx/paragon';
6+
import CourseFilesSlot from '../../plugin-slots/CourseFilesSlot';
67
import Placeholder from '../../editors/Placeholder';
78

89
import { RequestStatus } from '../../data/constants';
9-
import { useModels, useModel } from '../../generic/model-store';
10-
import {
11-
addAssetFile,
12-
deleteAssetFile,
13-
fetchAssets,
14-
updateAssetLock,
15-
fetchAssetDownload,
16-
getUsagePaths,
17-
resetErrors,
18-
updateAssetOrder,
19-
validateAssetFiles,
20-
} from './data/thunks';
21-
import messages from './messages';
22-
import FilesPageProvider from './FilesPageProvider';
10+
import { useModel } from '../../generic/model-store';
2311
import getPageHeadTitle from '../../generic/utils';
24-
import {
25-
AccessColumn,
26-
ActiveColumn,
27-
EditFileErrors,
28-
FileTable,
29-
ThumbnailColumn,
30-
} from '../generic';
31-
import { getFileSizeToClosestByte } from '../../utils';
32-
import FileThumbnail from './FileThumbnail';
33-
import FileInfoModalSidebar from './FileInfoModalSidebar';
34-
import FileValidationModal from './FileValidationModal';
12+
import { EditFileErrors } from '../generic';
13+
import { fetchAssets, resetErrors } from './data/thunks';
14+
import FilesPageProvider from './FilesPageProvider';
15+
import messages from './messages';
3516
import './FilesPage.scss';
3617

3718
const FilesPage = ({
@@ -41,133 +22,19 @@ const FilesPage = ({
4122
const dispatch = useDispatch();
4223
const courseDetails = useModel('courseDetails', courseId);
4324
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.heading));
44-
45-
useEffect(() => {
46-
dispatch(fetchAssets(courseId));
47-
}, [courseId]);
48-
4925
const {
50-
assetIds,
5126
loadingStatus,
5227
addingStatus: addAssetStatus,
5328
deletingStatus: deleteAssetStatus,
5429
updatingStatus: updateAssetStatus,
55-
usageStatus: usagePathStatus,
5630
errors: errorMessages,
5731
} = useSelector(state => state.assets);
5832

59-
const handleErrorReset = (error) => dispatch(resetErrors(error));
60-
const handleDeleteFile = (id) => dispatch(deleteAssetFile(courseId, id));
61-
const handleDownloadFile = (selectedRows) => dispatch(fetchAssetDownload({ selectedRows, courseId }));
62-
const handleAddFile = (files) => {
63-
handleErrorReset({ errorType: 'add' });
64-
dispatch(validateAssetFiles(courseId, files));
65-
};
66-
const handleFileOverwrite = (close, files) => {
67-
Object.values(files).forEach(file => dispatch(addAssetFile(courseId, file, true)));
68-
close();
69-
};
70-
const handleLockFile = (fileId, locked) => {
71-
handleErrorReset({ errorType: 'lock' });
72-
dispatch(updateAssetLock({ courseId, assetId: fileId, locked }));
73-
};
74-
const handleUsagePaths = (asset) => dispatch(getUsagePaths({ asset, courseId }));
75-
const handleFileOrder = ({ newFileIdOrder, sortType }) => {
76-
dispatch(updateAssetOrder(courseId, newFileIdOrder, sortType));
77-
};
78-
79-
const thumbnailPreview = (props) => FileThumbnail(props);
80-
const infoModalSidebar = (asset) => FileInfoModalSidebar({
81-
asset,
82-
handleLockedAsset: handleLockFile,
83-
});
84-
85-
const assets = useModels('assets', assetIds);
86-
const data = {
87-
fileIds: assetIds,
88-
loadingStatus,
89-
usagePathStatus,
90-
usageErrorMessages: errorMessages.usageMetrics,
91-
fileType: 'file',
92-
};
93-
const maxFileSize = 20 * 1048576;
94-
95-
const activeColumn = {
96-
id: 'activeStatus',
97-
Header: intl.formatMessage(messages.fileActiveColumn),
98-
accessor: 'activeStatus',
99-
Cell: ({ row }) => ActiveColumn({ row, pageLoadStatus: loadingStatus }),
100-
Filter: CheckboxFilter,
101-
filter: 'exactTextCase',
102-
filterChoices: [
103-
{ name: intl.formatMessage(messages.activeCheckboxLabel), value: 'active' },
104-
{ name: intl.formatMessage(messages.inactiveCheckboxLabel), value: 'inactive' },
105-
],
106-
};
107-
const accessColumn = {
108-
id: 'lockStatus',
109-
Header: intl.formatMessage(messages.fileAccessColumn),
110-
accessor: 'lockStatus',
111-
Cell: ({ row }) => AccessColumn({ row }),
112-
Filter: CheckboxFilter,
113-
filterChoices: [
114-
{ name: intl.formatMessage(messages.lockedCheckboxLabel), value: 'locked' },
115-
{ name: intl.formatMessage(messages.publicCheckboxLabel), value: 'public' },
116-
],
117-
};
118-
const thumbnailColumn = {
119-
id: 'thumbnail',
120-
Header: '',
121-
Cell: ({ row }) => ThumbnailColumn({ row, thumbnailPreview }),
122-
};
123-
const fileSizeColumn = {
124-
id: 'fileSize',
125-
Header: intl.formatMessage(messages.fileSizeColumn),
126-
accessor: 'fileSize',
127-
Cell: ({ row }) => {
128-
const { fileSize } = row.original;
129-
return getFileSizeToClosestByte(fileSize);
130-
},
131-
};
33+
useEffect(() => {
34+
dispatch(fetchAssets(courseId));
35+
}, [courseId]);
13236

133-
const tableColumns = [
134-
{ ...thumbnailColumn },
135-
{
136-
Header: intl.formatMessage(messages.fileNameColumn),
137-
accessor: 'displayName',
138-
},
139-
{ ...fileSizeColumn },
140-
{
141-
Header: intl.formatMessage(messages.fileTypeColumn),
142-
accessor: 'wrapperType',
143-
Filter: CheckboxFilter,
144-
filter: 'includesValue',
145-
filterChoices: [
146-
{
147-
name: intl.formatMessage(messages.codeCheckboxLabel),
148-
value: 'code',
149-
},
150-
{
151-
name: intl.formatMessage(messages.imageCheckboxLabel),
152-
value: 'image',
153-
},
154-
{
155-
name: intl.formatMessage(messages.documentCheckboxLabel),
156-
value: 'document',
157-
},
158-
{
159-
name: intl.formatMessage(messages.audioCheckboxLabel),
160-
value: 'audio',
161-
},
162-
{
163-
name: intl.formatMessage(messages.otherCheckboxLabel),
164-
value: 'other',
165-
},
166-
],
167-
},
168-
{ ...activeColumn },
169-
{ ...accessColumn },
170-
];
37+
const handleErrorReset = (error) => dispatch(resetErrors(error));
17138

17239
if (loadingStatus === RequestStatus.DENIED) {
17340
return (
@@ -189,30 +56,10 @@ const FilesPage = ({
18956
loadingStatus={loadingStatus}
19057
/>
19158
<div className="h2">
192-
<FormattedMessage {...messages.heading} />
59+
{intl.formatMessage(messages.heading)}
19360
</div>
19461
{loadingStatus !== RequestStatus.FAILED && (
195-
<>
196-
<FileTable
197-
{...{
198-
courseId,
199-
data,
200-
handleAddFile,
201-
handleDeleteFile,
202-
handleDownloadFile,
203-
handleLockFile,
204-
handleUsagePaths,
205-
handleErrorReset,
206-
handleFileOrder,
207-
tableColumns,
208-
maxFileSize,
209-
thumbnailPreview,
210-
infoModalSidebar,
211-
files: assets,
212-
}}
213-
/>
214-
<FileValidationModal {...{ handleFileOverwrite }} />
215-
</>
62+
<CourseFilesSlot courseId={courseId} />
21663
)}
21764
</Container>
21865
</FilesPageProvider>

src/files-and-videos/generic/EditFileErrors.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import PropTypes from 'prop-types';
33
import { useIntl } from '@edx/frontend-platform/i18n';
44
import { Alert } from '@openedx/paragon';
5+
import EditFileErrorAlertsSlot from '../../plugin-slots/EditFileErrorAlertsSlot';
56
import ErrorAlert from '../../editors/sharedComponents/ErrorAlerts/ErrorAlert';
67
import { RequestStatus } from '../../data/constants';
78
import messages from './messages';
@@ -76,6 +77,7 @@ const EditFileErrors = ({
7677
))}
7778
</ul>
7879
</ErrorAlert>
80+
<EditFileErrorAlertsSlot />
7981
</>
8082
);
8183
};

0 commit comments

Comments
 (0)