Skip to content

Commit 734b4c9

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 311bef6 commit 734b4c9

22 files changed

Lines changed: 751 additions & 463 deletions

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
};
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import { useIntl } from '@edx/frontend-platform/i18n';
2+
import { CheckboxFilter } from '@openedx/paragon';
3+
import {
4+
addAssetFile,
5+
deleteAssetFile,
6+
fetchAssetDownload,
7+
getUsagePaths,
8+
resetErrors,
9+
updateAssetLock,
10+
updateAssetOrder,
11+
validateAssetFiles,
12+
} from '@src/files-and-videos/files-page/data/thunks';
13+
import FileInfoModalSidebar from '@src/files-and-videos/files-page/FileInfoModalSidebar';
14+
import FileThumbnail from '@src/files-and-videos/files-page/FileThumbnail';
15+
import FileValidationModal from '@src/files-and-videos/files-page/FileValidationModal';
16+
import messages from '@src/files-and-videos/files-page/messages';
17+
import {
18+
AccessColumn,
19+
ActiveColumn,
20+
FileTable,
21+
ThumbnailColumn,
22+
} from '@src/files-and-videos/generic';
23+
import { useModels } from '@src/generic/model-store';
24+
import { DeprecatedReduxState } from '@src/store';
25+
import { getFileSizeToClosestByte } from '@src/utils';
26+
import React from 'react';
27+
import { useDispatch, useSelector } from 'react-redux';
28+
import { useParams } from 'react-router-dom';
29+
30+
export const CourseFilesTable = () => {
31+
const intl = useIntl();
32+
const { courseId } = useParams() as { courseId: string };
33+
const dispatch = useDispatch();
34+
const {
35+
assetIds,
36+
loadingStatus,
37+
usageStatus: usagePathStatus,
38+
errors: errorMessages,
39+
} = useSelector((state: DeprecatedReduxState) => state.assets);
40+
41+
const handleErrorReset = (error) => dispatch(resetErrors(error));
42+
const handleDeleteFile = (id) => dispatch(deleteAssetFile(courseId, id));
43+
const handleDownloadFile = (selectedRows) => dispatch(fetchAssetDownload({
44+
selectedRows,
45+
courseId,
46+
}));
47+
const handleAddFile = (files) => {
48+
handleErrorReset({ errorType: 'add' });
49+
dispatch(validateAssetFiles(courseId, files));
50+
};
51+
const handleFileOverwrite = (close, files) => {
52+
Object.values(files).forEach(file => dispatch(addAssetFile(courseId, file, true)));
53+
close();
54+
};
55+
const handleLockFile = (fileId, locked) => {
56+
handleErrorReset({ errorType: 'lock' });
57+
dispatch(updateAssetLock({ courseId, assetId: fileId, locked }));
58+
};
59+
const handleUsagePaths = (asset) => dispatch(getUsagePaths({ asset, courseId }));
60+
const handleFileOrder = ({ newFileIdOrder }) => {
61+
dispatch(updateAssetOrder(courseId, newFileIdOrder));
62+
};
63+
64+
const thumbnailPreview = (props) => FileThumbnail(props);
65+
const infoModalSidebar = (asset) => FileInfoModalSidebar({
66+
asset,
67+
handleLockedAsset: handleLockFile,
68+
});
69+
70+
const assets = useModels('assets', assetIds);
71+
const data = {
72+
fileIds: assetIds,
73+
loadingStatus,
74+
usagePathStatus,
75+
usageErrorMessages: errorMessages.usageMetrics,
76+
fileType: 'file',
77+
};
78+
const maxFileSize = 20 * 1048576;
79+
80+
const activeColumn = {
81+
id: 'activeStatus',
82+
Header: intl.formatMessage(messages.fileActiveColumn),
83+
accessor: 'activeStatus',
84+
Cell: ({ row }) => ActiveColumn({ row, pageLoadStatus: loadingStatus }),
85+
Filter: CheckboxFilter,
86+
filter: 'exactTextCase',
87+
filterChoices: [
88+
{ name: intl.formatMessage(messages.activeCheckboxLabel), value: 'active' },
89+
{ name: intl.formatMessage(messages.inactiveCheckboxLabel), value: 'inactive' },
90+
],
91+
};
92+
const accessColumn = {
93+
id: 'lockStatus',
94+
Header: intl.formatMessage(messages.fileAccessColumn),
95+
accessor: 'lockStatus',
96+
Cell: ({ row }) => AccessColumn({ row }),
97+
Filter: CheckboxFilter,
98+
filterChoices: [
99+
{ name: intl.formatMessage(messages.lockedCheckboxLabel), value: 'locked' },
100+
{ name: intl.formatMessage(messages.publicCheckboxLabel), value: 'public' },
101+
],
102+
};
103+
const thumbnailColumn = {
104+
id: 'thumbnail',
105+
Header: '',
106+
Cell: ({ row }) => ThumbnailColumn({ row, thumbnailPreview }),
107+
};
108+
const fileSizeColumn = {
109+
id: 'fileSize',
110+
Header: intl.formatMessage(messages.fileSizeColumn),
111+
accessor: 'fileSize',
112+
Cell: ({ row }) => {
113+
const { fileSize } = row.original;
114+
return getFileSizeToClosestByte(fileSize);
115+
},
116+
};
117+
118+
const tableColumns = [
119+
{ ...thumbnailColumn },
120+
{
121+
Header: intl.formatMessage(messages.fileNameColumn),
122+
accessor: 'displayName',
123+
},
124+
{ ...fileSizeColumn },
125+
{
126+
Header: intl.formatMessage(messages.fileTypeColumn),
127+
accessor: 'wrapperType',
128+
Filter: CheckboxFilter,
129+
filter: 'includesValue',
130+
filterChoices: [
131+
{
132+
name: intl.formatMessage(messages.codeCheckboxLabel),
133+
value: 'code',
134+
},
135+
{
136+
name: intl.formatMessage(messages.imageCheckboxLabel),
137+
value: 'image',
138+
},
139+
{
140+
name: intl.formatMessage(messages.documentCheckboxLabel),
141+
value: 'document',
142+
},
143+
{
144+
name: intl.formatMessage(messages.audioCheckboxLabel),
145+
value: 'audio',
146+
},
147+
{
148+
name: intl.formatMessage(messages.otherCheckboxLabel),
149+
value: 'other',
150+
},
151+
],
152+
},
153+
{ ...activeColumn },
154+
{ ...accessColumn },
155+
];
156+
157+
if (!courseId) {
158+
return null;
159+
}
160+
return (
161+
<>
162+
<FileTable
163+
{...{
164+
courseId,
165+
data,
166+
handleAddFile,
167+
handleDeleteFile,
168+
handleDownloadFile,
169+
handleLockFile,
170+
handleUsagePaths,
171+
handleErrorReset,
172+
handleFileOrder,
173+
tableColumns,
174+
maxFileSize,
175+
thumbnailPreview,
176+
infoModalSidebar,
177+
files: assets,
178+
}}
179+
/>
180+
<FileValidationModal {...{ handleFileOverwrite }} />
181+
</>
182+
);
183+
};

0 commit comments

Comments
 (0)