refactor: files-and-videos folder (#672)

This commit is contained in:
Kristin Aoki
2023-11-08 15:54:47 -05:00
committed by GitHub
parent 3dac6aa188
commit 78eb512836
49 changed files with 226 additions and 178 deletions

View File

@@ -18,10 +18,10 @@ import {
} from '@edx/paragon';
import { ContentCopy, InfoOutline } from '@edx/paragon/icons';
import { getFileSizeToClosestByte } from '../data/utils';
import { getFileSizeToClosestByte } from '../generic/utils';
import messages from './messages';
const FileInfoAssetSidebar = ({
const FileInfoModalSidebar = ({
asset,
handleLockedAsset,
// injected
@@ -109,7 +109,7 @@ const FileInfoAssetSidebar = ({
</Stack>
);
};
FileInfoAssetSidebar.propTypes = {
FileInfoModalSidebar.propTypes = {
asset: PropTypes.shape({
displayName: PropTypes.string.isRequired,
wrapperType: PropTypes.string.isRequired,
@@ -127,4 +127,4 @@ FileInfoAssetSidebar.propTypes = {
intl: intlShape.isRequired,
};
export default injectIntl(FileInfoAssetSidebar);
export default injectIntl(FileInfoModalSidebar);

View File

@@ -5,10 +5,10 @@ import {
Icon,
Image,
} from '@edx/paragon';
import { getSrc } from '../data/utils';
import { getSrc } from './data/utils';
import messages from './messages';
const AssetThumbnail = ({
const FileThumbnail = ({
thumbnail,
wrapperType,
externalUrl,
@@ -50,13 +50,13 @@ const AssetThumbnail = ({
</div>
);
};
AssetThumbnail.defaultProps = {
FileThumbnail.defaultProps = {
thumbnail: null,
wrapperType: null,
externalUrl: null,
displayName: null,
};
AssetThumbnail.propTypes = {
FileThumbnail.propTypes = {
thumbnail: PropTypes.string,
wrapperType: PropTypes.string,
externalUrl: PropTypes.string,
@@ -69,4 +69,4 @@ AssetThumbnail.propTypes = {
intl: intlShape.isRequired,
};
export default injectIntl(AssetThumbnail);
export default injectIntl(FileThumbnail);

View File

@@ -16,19 +16,22 @@ import {
getUsagePaths,
resetErrors,
updateAssetOrder,
} from '../data/thunks';
} from './data/thunks';
import messages from './messages';
import FilesAndUploadsProvider from './FilesAndUploadsProvider';
import FilesPageProvider from './FilesPageProvider';
import getPageHeadTitle from '../../generic/utils';
import FileTable from '../FileTable';
import EditFileErrors from '../EditFileErrors';
import { getFileSizeToClosestByte } from '../data/utils';
import ThumbnailColumn from '../table-components/table-custom-columns/ThumbnailColumn';
import ActiveColumn from '../table-components/table-custom-columns/ActiveColumn';
import AccessColumn from '../table-components/table-custom-columns/AccessColumn';
import AssetThumbnail from './AssetThumbnail';
import {
AccessColumn,
ActiveColumn,
EditFileErrors,
FileTable,
ThumbnailColumn,
} from '../generic';
import { getFileSizeToClosestByte } from '../generic/utils';
import FileThumbnail from './FileThumbnail';
import FileInfoModalSidebar from './FileInfoModalSidebar';
const FilesAndUploads = ({
const FilesPage = ({
courseId,
// injected
intl,
@@ -52,17 +55,24 @@ const FilesAndUploads = ({
errors: errorMessages,
} = useSelector(state => state.assets);
const handleErrorReset = (error) => dispatch(resetErrors(error));
const handleAddFile = (file) => dispatch(addAssetFile(courseId, file, totalCount));
const handleDeleteFile = (id) => dispatch(deleteAssetFile(courseId, id, totalCount));
const handleDownloadFile = (selectedRows) => dispatch(fetchAssetDownload({ selectedRows, courseId }));
const handleLockFile = ({ fileId, locked }) => dispatch(updateAssetLock({ courseId, assetId: fileId, locked }));
const handleLockFile = (fileId, locked) => {
handleErrorReset({ errorType: 'lock' });
dispatch(updateAssetLock({ courseId, assetId: fileId, locked }));
};
const handleUsagePaths = (asset) => dispatch(getUsagePaths({ asset, courseId }));
const handleErrorReset = (error) => dispatch(resetErrors(error));
const handleFileOrder = ({ newFileIdOrder, sortType }) => {
dispatch(updateAssetOrder(courseId, newFileIdOrder, sortType));
};
const thumbnailPreview = (props) => AssetThumbnail(props);
const thumbnailPreview = (props) => FileThumbnail(props);
const infoModalSidebar = (asset) => FileInfoModalSidebar({
asset,
handleLockedAsset: handleLockFile,
});
const assets = useModels('assets', assetIds);
const data = {
@@ -141,7 +151,7 @@ const FilesAndUploads = ({
);
}
return (
<FilesAndUploadsProvider courseId={courseId}>
<FilesPageProvider courseId={courseId}>
<main>
<div className="p-4">
<EditFileErrors
@@ -169,18 +179,19 @@ const FilesAndUploads = ({
tableColumns,
maxFileSize,
thumbnailPreview,
infoModalSidebar,
files: assets,
}}
/>
</main>
</FilesAndUploadsProvider>
</FilesPageProvider>
);
};
FilesAndUploads.propTypes = {
FilesPage.propTypes = {
courseId: PropTypes.string.isRequired,
// injected
intl: intlShape.isRequired,
};
export default injectIntl(FilesAndUploads);
export default injectIntl(FilesPage);

View File

@@ -19,7 +19,7 @@ import { IntlProvider } from '@edx/frontend-platform/i18n';
import initializeStore from '../../store';
import { executeThunk } from '../../utils';
import { RequestStatus } from '../../data/constants';
import FilesAndUploads from './FilesAndUploads';
import FilesPage from './FilesPage';
import {
generateFetchAssetApiResponse,
generateEmptyApiResponse,
@@ -35,9 +35,9 @@ import {
deleteAssetFile,
updateAssetLock,
getUsagePaths,
} from '../data/thunks';
import { getAssetsUrl } from '../data/api';
import messages from '../messages';
} from './data/thunks';
import { getAssetsUrl } from './data/api';
import messages from '../generic/messages';
let axiosMock;
let store;
@@ -49,7 +49,7 @@ const renderComponent = () => {
render(
<IntlProvider locale="en">
<AppProvider store={store}>
<FilesAndUploads courseId={courseId} />
<FilesPage courseId={courseId} />
</AppProvider>
</IntlProvider>,
);

View File

@@ -1,25 +1,25 @@
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
export const FilesAndUploadsContext = React.createContext({});
export const FilesPageContext = React.createContext({});
const FilesAndUploadsProvider = ({ courseId, children }) => {
const FilesPageProvider = ({ courseId, children }) => {
const contextValue = useMemo(() => ({
courseId,
path: `/course/${courseId}/assets`,
}), []);
return (
<FilesAndUploadsContext.Provider
<FilesPageContext.Provider
value={contextValue}
>
{children}
</FilesAndUploadsContext.Provider>
</FilesPageContext.Provider>
);
};
FilesAndUploadsProvider.propTypes = {
FilesPageProvider.propTypes = {
courseId: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
};
export default FilesAndUploadsProvider;
export default FilesPageProvider;

View File

@@ -1,7 +1,7 @@
/* eslint-disable no-param-reassign */
import { createSlice } from '@reduxjs/toolkit';
import { RequestStatus } from '../../data/constants';
import { RequestStatus } from '../../../data/constants';
const slice = createSlice({
name: 'assets',

View File

@@ -1,11 +1,11 @@
import { isEmpty } from 'lodash';
import { RequestStatus } from '../../data/constants';
import { RequestStatus } from '../../../data/constants';
import {
addModel,
addModels,
removeModel,
updateModel,
} from '../../generic/model-store';
} from '../../../generic/model-store';
import {
getAssets,
getAssetUsagePaths,

View File

@@ -4,7 +4,7 @@ import {
AudioFile,
} from '@edx/paragon/icons';
import { ensureConfig, getConfig } from '@edx/frontend-platform';
import FILES_AND_UPLOAD_TYPE_FILTERS from './constant';
import FILES_AND_UPLOAD_TYPE_FILTERS from '../../generic/constants';
ensureConfig([
'STUDIO_BASE_URL',
@@ -54,55 +54,3 @@ export const getSrc = ({ thumbnail, wrapperType, externalUrl }) => {
return InsertDriveFile;
}
};
export const getFileSizeToClosestByte = (fileSize, numberOfDivides = 0) => {
if (fileSize > 1000) {
const updatedSize = fileSize / 1000;
const incrementNumberOfDivides = numberOfDivides + 1;
return getFileSizeToClosestByte(updatedSize, incrementNumberOfDivides);
}
const fileSizeFixedDecimal = Number.parseFloat(fileSize).toFixed(2);
switch (numberOfDivides) {
case 1:
return `${fileSizeFixedDecimal} KB`;
case 2:
return `${fileSizeFixedDecimal} MB`;
case 3:
return `${fileSizeFixedDecimal} GB`;
default:
return `${fileSizeFixedDecimal} B`;
}
};
export const sortFiles = (files, sortType) => {
const [sort, direction] = sortType.split(',');
let sortedFiles;
if (sort === 'displayName') {
sortedFiles = files.sort((f1, f2) => {
const lowerCaseF1 = f1[sort].toLowerCase();
const lowerCaseF2 = f2[sort].toLowerCase();
if (lowerCaseF1 < lowerCaseF2) {
return 1;
}
if (lowerCaseF1 > lowerCaseF2) {
return -1;
}
return 0;
});
} else {
sortedFiles = files.sort((f1, f2) => {
if (f1[sort] < f2[sort]) {
return 1;
}
if (f1[sort] > f2[sort]) {
return -1;
}
return 0;
});
}
const sortedIds = sortedFiles.map(file => file.id);
if (direction === 'asc') {
return sortedIds.reverse();
}
return sortedIds;
};

View File

@@ -1,3 +1,5 @@
import FilesAndUploads from './FilesAndUploads';
import FilesPage from './FilesPage';
import FileInfoModalSidebar from './FileInfoModalSidebar';
export default FilesAndUploads;
export default FilesPage;
export { FileInfoModalSidebar };

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { ErrorAlert } from '@edx/frontend-lib-content-components';
import { RequestStatus } from '../data/constants';
import { RequestStatus } from '../../data/constants';
import messages from './messages';
const EditFileErrors = ({

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { getSupportedFormats } from './videos-page/data/utils';
import { getSupportedFormats } from '../videos-page/data/utils';
export const useFileInput = ({
onAddFile,

View File

@@ -13,11 +13,11 @@ import {
Button,
} from '@edx/paragon';
import { RequestStatus } from '../data/constants';
import { sortFiles } from './data/utils';
import { RequestStatus } from '../../data/constants';
import { sortFiles } from './utils';
import messages from './messages';
import FileInfo from './FileInfo';
import InfoModal from './InfoModal';
import FileInput, { useFileInput } from './FileInput';
import {
GalleryCard,
@@ -40,6 +40,7 @@ const FileTable = ({
tableColumns,
maxFileSize,
thumbnailPreview,
infoModalSidebar,
// injected
intl,
}) => {
@@ -112,11 +113,6 @@ const FileTable = ({
handleDownloadFile(selectedFlatRows);
}, []);
const handleLockedFile = (fileId, locked) => {
handleErrorReset({ errorType: 'lock' });
handleLockFile({ fileId, locked });
};
const handleOpenDeleteConfirmation = (selectedFlatRows) => {
setSelectedRows(selectedFlatRows);
openDeleteConfirmation();
@@ -146,7 +142,7 @@ const FileTable = ({
const fileCard = ({ className, original }) => (
<GalleryCard
{...{
handleLockedFile,
handleLockFile,
handleBulkDownload,
handleOpenDeleteConfirmation,
handleOpenFileInfo,
@@ -162,7 +158,7 @@ const FileTable = ({
Header: '',
Cell: ({ row }) => MoreInfoColumn({
row,
handleLock: handleLockedFile,
handleLock: handleLockFile,
handleBulkDownload,
handleOpenFileInfo,
handleOpenDeleteConfirmation,
@@ -238,14 +234,14 @@ const FileTable = ({
</DataTable>
<FileInput key="generic-file-upload" fileInput={fileInputControl} supportedFileFormats={supportedFileFormats} />
{!isEmpty(selectedRows) && (
<FileInfo
<InfoModal
file={selectedRows[0].original}
onClose={closeAssetinfo}
isOpen={isAssetInfoOpen}
handleLockedFile={handleLockedFile}
thumbnailPreview={thumbnailPreview}
usagePathStatus={usagePathStatus}
error={usageErrorMessages}
sidebar={infoModalSidebar}
/>
)}
<AlertModal
@@ -294,6 +290,7 @@ FileTable.propTypes = {
})).isRequired,
maxFileSize: PropTypes.number.isRequired,
thumbnailPreview: PropTypes.func.isRequired,
infoModalSidebar: PropTypes.func.isRequired,
// injected
intl: intlShape.isRequired,
};

View File

@@ -12,18 +12,16 @@ import {
import messages from './messages';
import UsageMetricsMessages from './UsageMetricsMessage';
import FileInfoAssetSidebar from './files-page/FileInfoAssetSidebar';
import FileInfoVideoSidebar from './videos-page/info-sidebar/FileInfoVideoSidebar';
import FileThumbnail from './FileThumbnail';
import FileThumbnail from './ThumbnailPreview';
const FileInfo = ({
const InfoModal = ({
file,
isOpen,
onClose,
handleLockedFile,
thumbnailPreview,
usagePathStatus,
error,
sidebar,
}) => (
<ModalDialog
title={file?.displayName}
@@ -58,11 +56,7 @@ const FileInfo = ({
/>
</div>
<div className="col-5">
{file?.wrapperType === 'video' ? (
<FileInfoVideoSidebar video={file} />
) : (
<FileInfoAssetSidebar asset={file} handleLockedAsset={handleLockedFile} />
)}
{sidebar(file)}
</div>
</div>
<div className="row m-0 pt-3 font-weight-bold">
@@ -73,7 +67,7 @@ const FileInfo = ({
</ModalDialog>
);
FileInfo.propTypes = {
InfoModal.propTypes = {
file: PropTypes.shape({
displayName: PropTypes.string.isRequired,
wrapperType: PropTypes.string.isRequired,
@@ -89,14 +83,14 @@ FileInfo.propTypes = {
}),
onClose: PropTypes.func.isRequired,
isOpen: PropTypes.bool.isRequired,
handleLockedFile: PropTypes.func.isRequired,
usagePathStatus: PropTypes.string.isRequired,
error: PropTypes.arrayOf(PropTypes.string).isRequired,
thumbnailPreview: PropTypes.func.isRequired,
sidebar: PropTypes.func.isRequired,
};
FileInfo.defaultProps = {
InfoModal.defaultProps = {
file: null,
};
export default injectIntl(FileInfo);
export default injectIntl(InfoModal);

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
const FileThumbnail = ({
const ThumbnailPreview = ({
thumbnail,
wrapperType,
externalUrl,
@@ -23,7 +23,7 @@ const FileThumbnail = ({
})}
</>
);
FileThumbnail.defaultProps = {
ThumbnailPreview.defaultProps = {
thumbnail: null,
wrapperType: null,
externalUrl: null,
@@ -31,7 +31,7 @@ FileThumbnail.defaultProps = {
id: null,
status: null,
};
FileThumbnail.propTypes = {
ThumbnailPreview.propTypes = {
thumbnail: PropTypes.string,
wrapperType: PropTypes.string,
externalUrl: PropTypes.string,
@@ -45,4 +45,4 @@ FileThumbnail.propTypes = {
}).isRequired,
};
export default FileThumbnail;
export default ThumbnailPreview;

View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { Icon, Row, Spinner } from '@edx/paragon';
import { ErrorOutline } from '@edx/paragon/icons';
import isEmpty from 'lodash/isEmpty';
import { RequestStatus } from '../data/constants';
import { RequestStatus } from '../../data/constants';
import messages from './messages';
const UsageMetricsMessage = ({

View File

@@ -0,0 +1,24 @@
import {
TableActions,
GalleryCard,
AccessColumn,
ActiveColumn,
MoreInfoColumn,
StatusColumn,
ThumbnailColumn,
} from './table-components';
import FileInput, { useFileInput } from './FileInput';
export {
TableActions,
GalleryCard,
AccessColumn,
ActiveColumn,
MoreInfoColumn,
StatusColumn,
ThumbnailColumn,
FileInput,
useFileInput,
};
export { default as FileTable } from './FileTable';
export { default as EditFileErrors } from './EditFileErrors';

View File

@@ -9,20 +9,20 @@ import {
} from '@edx/paragon';
import { ClosedCaption } from '@edx/paragon/icons';
import FileMenu from '../FileMenu';
import FileThumbnail from '../FileThumbnail';
import FileThumbnail from '../ThumbnailPreview';
const GalleryCard = ({
className,
original,
handleBulkDownload,
handleLockedFile,
handleLockFile,
handleOpenDeleteConfirmation,
handleOpenFileInfo,
thumbnailPreview,
}) => {
const lockFile = () => {
const { locked, id } = original;
handleLockedFile(id, !locked);
handleLockFile(id, !locked);
};
return (
@@ -99,7 +99,7 @@ GalleryCard.propTypes = {
downloadLink: PropTypes.string,
}).isRequired,
handleBulkDownload: PropTypes.func.isRequired,
handleLockedFile: PropTypes.func.isRequired,
handleLockFile: PropTypes.func.isRequired,
handleOpenDeleteConfirmation: PropTypes.func.isRequired,
handleOpenFileInfo: PropTypes.func.isRequired,
thumbnailPreview: PropTypes.func.isRequired,

View File

@@ -0,0 +1,19 @@
import GalleryCard from './GalleryCard';
import TableActions from './TableActions';
import {
AccessColumn,
ActiveColumn,
MoreInfoColumn,
StatusColumn,
ThumbnailColumn,
} from './table-custom-columns';
export {
TableActions,
GalleryCard,
AccessColumn,
ActiveColumn,
MoreInfoColumn,
StatusColumn,
ThumbnailColumn,
};

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { PropTypes } from 'prop-types';
import FileThumbnail from '../../FileThumbnail';
import ThumbnailPreview from '../../ThumbnailPreview';
const ThumbnailColumn = ({ row, thumbnailPreview }) => {
const {
@@ -12,7 +12,7 @@ const ThumbnailColumn = ({ row, thumbnailPreview }) => {
status,
} = row.original;
return (
<FileThumbnail
<ThumbnailPreview
{...{
thumbnail,
wrapperType,

View File

@@ -0,0 +1,51 @@
export const getFileSizeToClosestByte = (fileSize, numberOfDivides = 0) => {
if (fileSize > 1000) {
const updatedSize = fileSize / 1000;
const incrementNumberOfDivides = numberOfDivides + 1;
return getFileSizeToClosestByte(updatedSize, incrementNumberOfDivides);
}
const fileSizeFixedDecimal = Number.parseFloat(fileSize).toFixed(2);
switch (numberOfDivides) {
case 1:
return `${fileSizeFixedDecimal} KB`;
case 2:
return `${fileSizeFixedDecimal} MB`;
case 3:
return `${fileSizeFixedDecimal} GB`;
default:
return `${fileSizeFixedDecimal} B`;
}
};
export const sortFiles = (files, sortType) => {
const [sort, direction] = sortType.split(',');
let sortedFiles;
if (sort === 'displayName') {
sortedFiles = files.sort((f1, f2) => {
const lowerCaseF1 = f1[sort].toLowerCase();
const lowerCaseF2 = f2[sort].toLowerCase();
if (lowerCaseF1 < lowerCaseF2) {
return 1;
}
if (lowerCaseF1 > lowerCaseF2) {
return -1;
}
return 0;
});
} else {
sortedFiles = files.sort((f1, f2) => {
if (f1[sort] < f2[sort]) {
return 1;
}
if (f1[sort] > f2[sort]) {
return -1;
}
return 0;
});
}
const sortedIds = sortedFiles.map(file => file.id);
if (direction === 'asc') {
return sortedIds.reverse();
}
return sortedIds;
};

View File

@@ -1,3 +1,3 @@
@import "files-and-videos/videos-page/transcript-settings/TranscriptSettings";
@import "files-and-videos/videos-page/VideoThumbnail";
@import "files-and-videos/table-components/GalleryCard"
@import "files-and-videos/generic/table-components/GalleryCard"

View File

@@ -1,7 +0,0 @@
import GalleryCard from './GalleryCard';
import TableActions from './TableActions';
export {
TableActions,
GalleryCard,
};

View File

@@ -8,7 +8,7 @@ import {
Icon,
Image,
} from '@edx/paragon';
import FileInput, { useFileInput } from '../FileInput';
import { FileInput, useFileInput } from '../generic';
import messages from './messages';
const VideoThumbnail = ({

View File

@@ -26,19 +26,22 @@ import {
updateVideoOrder,
} from './data/thunks';
import messages from './messages';
import VideosProvider from './VideosProvider';
import VideosPageProvider from './VideosPageProvider';
import getPageHeadTitle from '../../generic/utils';
import FileTable from '../FileTable';
import EditFileErrors from '../EditFileErrors';
import ThumbnailColumn from '../table-components/table-custom-columns/ThumbnailColumn';
import ActiveColumn from '../table-components/table-custom-columns/ActiveColumn';
import StatusColumn from '../table-components/table-custom-columns/StatusColumn';
import {
ActiveColumn,
EditFileErrors,
FileTable,
StatusColumn,
ThumbnailColumn,
} from '../generic';
import TranscriptSettings from './transcript-settings';
import VideoThumbnail from './VideoThumbnail';
import { getFormattedDuration, resampleFile } from './data/utils';
import FILES_AND_UPLOAD_TYPE_FILTERS from '../data/constant';
import FILES_AND_UPLOAD_TYPE_FILTERS from '../generic/constants';
import VideoInfoModalSidebar from './info-sidebar';
const Videos = ({
const VideosPage = ({
courseId,
// injected
intl,
@@ -103,6 +106,7 @@ const Videos = ({
usageErrorMessages: errorMessages.usageMetrics,
};
const thumbnailPreview = (props) => VideoThumbnail({ ...props, handleAddThumbnail, videoImageSettings });
const infoModalSidebar = (video) => VideoInfoModalSidebar({ video });
const maxFileSize = videoUploadMaxFileSize * 1073741824;
const transcriptColumn = {
id: 'transcripts',
@@ -156,7 +160,7 @@ const Videos = ({
);
}
return (
<VideosProvider courseId={courseId}>
<VideosPageProvider courseId={courseId}>
<main>
<div className="p-4">
<EditFileErrors
@@ -210,18 +214,19 @@ const Videos = ({
tableColumns,
maxFileSize,
thumbnailPreview,
infoModalSidebar,
files: videos,
}}
/>
</main>
</VideosProvider>
</VideosPageProvider>
);
};
Videos.propTypes = {
VideosPage.propTypes = {
courseId: PropTypes.string.isRequired,
// injected
intl: intlShape.isRequired,
};
export default injectIntl(Videos);
export default injectIntl(VideosPage);

View File

@@ -17,7 +17,7 @@ import { IntlProvider } from '@edx/frontend-platform/i18n';
import initializeStore from '../../store';
import { executeThunk } from '../../utils';
import { RequestStatus } from '../../data/constants';
import Videos from './Videos';
import VideosPage from './VideosPage';
import {
generateFetchVideosApiResponse,
generateEmptyApiResponse,
@@ -38,7 +38,7 @@ import {
} from './data/thunks';
import { getVideosUrl, getCoursVideosApiUrl, getApiBaseUrl } from './data/api';
import videoMessages from './messages';
import messages from '../messages';
import messages from '../generic/messages';
let axiosMock;
let store;
@@ -49,7 +49,7 @@ const renderComponent = () => {
render(
<IntlProvider locale="en">
<AppProvider store={store}>
<Videos courseId={courseId} />
<VideosPage courseId={courseId} />
</AppProvider>
</IntlProvider>,
);

View File

@@ -1,25 +1,25 @@
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
export const VideosContext = React.createContext({});
export const VideosPageContext = React.createContext({});
const VideosProvider = ({ courseId, children }) => {
const VideosPageProvider = ({ courseId, children }) => {
const contextValue = useMemo(() => ({
courseId,
path: `/course/${courseId}/videos`,
}), []);
return (
<VideosContext.Provider
<VideosPageContext.Provider
value={contextValue}
>
{children}
</VideosContext.Provider>
</VideosPageContext.Provider>
);
};
VideosProvider.propTypes = {
VideosPageProvider.propTypes = {
courseId: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
};
export default VideosProvider;
export default VideosPageProvider;

View File

@@ -1,6 +1,7 @@
import TranscriptSettings from './transcript-settings';
import Videos from './Videos';
import VideosPage from './VideosPage';
import VideoThumbnail from './VideoThumbnail';
import VideoInfoModalSidebar from './info-sidebar';
export default Videos;
export { TranscriptSettings, VideoThumbnail };
export default VideosPage;
export { TranscriptSettings, VideoThumbnail, VideoInfoModalSidebar };

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Stack } from '@edx/paragon';
import { injectIntl, FormattedDate, FormattedMessage } from '@edx/frontend-platform/i18n';
import { getFileSizeToClosestByte } from '../../data/utils';
import { getFileSizeToClosestByte } from '../../generic/utils';
import { getFormattedDuration } from '../data/utils';
import messages from './messages';

View File

@@ -28,7 +28,7 @@ import {
import { getApiBaseUrl } from '../data/api';
import messages from './messages';
import transcriptRowMessages from './transcript-item/messages';
import VideosProvider from '../VideosProvider';
import VideosPageProvider from '../VideosPageProvider';
import { deleteVideoTranscript } from '../data/thunks';
ReactDOM.createPortal = jest.fn(node => node);
@@ -56,9 +56,9 @@ const renderComponent = (props) => {
render(
<IntlProvider locale="en">
<AppProvider store={store}>
<VideosProvider courseId={courseId}>
<VideosPageProvider courseId={courseId}>
<TranscriptTab video={props} />
</VideosProvider>
</VideosPageProvider>
</AppProvider>
</IntlProvider>,
);

View File

@@ -9,7 +9,7 @@ import InfoTab from './InfoTab';
import TranscriptTab from './TranscriptTab';
import messages from './messages';
const FileInfoVideoSidebar = ({
const VideoInfoModalSidebar = ({
video,
// injected
intl,
@@ -30,7 +30,7 @@ const FileInfoVideoSidebar = ({
</Tabs>
);
FileInfoVideoSidebar.propTypes = {
VideoInfoModalSidebar.propTypes = {
video: PropTypes.shape({
displayName: PropTypes.string.isRequired,
wrapperType: PropTypes.string.isRequired,
@@ -43,8 +43,8 @@ FileInfoVideoSidebar.propTypes = {
intl: intlShape.isRequired,
};
FileInfoVideoSidebar.defaultProps = {
VideoInfoModalSidebar.defaultProps = {
video: null,
};
export default injectIntl(FileInfoVideoSidebar);
export default injectIntl(VideoInfoModalSidebar);

View File

@@ -0,0 +1,3 @@
import VideoInfoModalSidebar from './VideoInfoModalSidebar';
export default VideoInfoModalSidebar;

View File

@@ -13,7 +13,7 @@ import { isEmpty } from 'lodash';
import LanguageSelect from './LanguageSelect';
import TranscriptMenu from './TranscriptMenu';
import messages from './messages';
import FileInput, { useFileInput } from '../../../FileInput';
import { FileInput, useFileInput } from '../../../generic';
const Transcript = ({
languages,

View File

@@ -21,7 +21,7 @@ import {
} from '../factories/mockApiResponses';
import { getApiBaseUrl } from '../data/api';
import messages from './messages';
import VideosProvider from '../VideosProvider';
import VideosProvider from '../VideosPageProvider';
const defaultProps = {
isTranscriptSettingsOpen: true,

View File

@@ -10,7 +10,7 @@ import { reducer as gradingSettingsReducer } from './grading-settings/data/slice
import { reducer as studioHomeReducer } from './studio-home/data/slice';
import { reducer as scheduleAndDetailsReducer } from './schedule-and-details/data/slice';
import { reducer as liveReducer } from './pages-and-resources/live/data/slice';
import { reducer as filesReducer } from './files-and-videos/data/slice';
import { reducer as filesReducer } from './files-and-videos/files-page/data/slice';
import { reducer as courseTeamReducer } from './course-team/data/slice';
import { reducer as CourseUpdatesReducer } from './course-updates/data/slice';
import { reducer as processingNotificationReducer } from './generic/processing-notification/data/slice';