fix: video editor and uploader layout fixes (#410)
* fix: video upload page layout fixes * fix: video editor thumbnail fallback icon colour and size * fix: video uploader close button go back instead of closing app Change the video uploader close button to always go back in navigation history, and change the gallery to replace its location with the video uploader's when automatically loading it due to an empty video list, so that when the uploader goes back in the history, it goes to what was before the gallery. * fix: video editor spinners vertical alignment The Editor component uses the pgn__modal-fullscreen class to be fullscreen, but it is not structured like a Paragon FullscreenModal and the fullscreen positioning style is not applied correctly, particularly in the case where the content is smaller than the body - a vertically centred component will be centred to the content size, not to the screen. Here we directly apply the style that would have applied to the relevant elements of a Paragon FullscreenModal. * fix: use trailingElement for video uploader input button Also styles the button so it looks the same on hover/active.
This commit is contained in:
@@ -31,9 +31,19 @@ export const Editor = ({
|
||||
|
||||
const EditorComponent = supportedEditors[blockType];
|
||||
return (
|
||||
<div className="d-flex flex-column">
|
||||
<div
|
||||
className="d-flex flex-column"
|
||||
style={{
|
||||
/* Positioned as a proper Paragon FullscreenModal should have been. */
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="pgn__modal-fullscreen"
|
||||
className="pgn__modal-fullscreen h-100"
|
||||
role="dialog"
|
||||
aria-label={blockType}
|
||||
>
|
||||
|
||||
@@ -3,10 +3,19 @@
|
||||
exports[`Editor render presents error message if no relevant editor found and ref ready 1`] = `
|
||||
<div
|
||||
className="d-flex flex-column"
|
||||
style={
|
||||
Object {
|
||||
"height": "100%",
|
||||
"left": 0,
|
||||
"position": "fixed",
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
aria-label="fAkEBlock"
|
||||
className="pgn__modal-fullscreen"
|
||||
className="pgn__modal-fullscreen h-100"
|
||||
role="dialog"
|
||||
>
|
||||
<FormattedMessage
|
||||
@@ -21,10 +30,19 @@ exports[`Editor render presents error message if no relevant editor found and re
|
||||
exports[`Editor render snapshot: renders correct editor given blockType (html -> TextEditor) 1`] = `
|
||||
<div
|
||||
className="d-flex flex-column"
|
||||
style={
|
||||
Object {
|
||||
"height": "100%",
|
||||
"left": 0,
|
||||
"position": "fixed",
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
aria-label="html"
|
||||
className="pgn__modal-fullscreen"
|
||||
className="pgn__modal-fullscreen h-100"
|
||||
role="dialog"
|
||||
>
|
||||
<TextEditor
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
exports[`EditorContainer component render snapshot: initialized. enable save and pass to header 1`] = `
|
||||
<div
|
||||
className="position-relative zindex-0"
|
||||
className="d-flex flex-column position-relative zindex-0"
|
||||
style={
|
||||
Object {
|
||||
"minHeight": "100%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<BaseModal
|
||||
bodyStyle={null}
|
||||
@@ -53,7 +58,7 @@ exports[`EditorContainer component render snapshot: initialized. enable save and
|
||||
</div>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body
|
||||
className="pb-6"
|
||||
className="pb-0 mb-6"
|
||||
>
|
||||
<h1>
|
||||
My test content
|
||||
@@ -78,7 +83,12 @@ exports[`EditorContainer component render snapshot: initialized. enable save and
|
||||
|
||||
exports[`EditorContainer component render snapshot: not initialized. disable save and pass to header 1`] = `
|
||||
<div
|
||||
className="position-relative zindex-0"
|
||||
className="d-flex flex-column position-relative zindex-0"
|
||||
style={
|
||||
Object {
|
||||
"minHeight": "100%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<BaseModal
|
||||
bodyStyle={null}
|
||||
@@ -129,7 +139,7 @@ exports[`EditorContainer component render snapshot: not initialized. disable sav
|
||||
</div>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body
|
||||
className="pb-6"
|
||||
className="pb-0 mb-6"
|
||||
/>
|
||||
<injectIntl(ShimmedIntlComponent)
|
||||
disableSave={true}
|
||||
|
||||
@@ -29,7 +29,8 @@ export const EditorContainer = ({
|
||||
const handleCancel = hooks.handleCancel({ onClose, returnFunction });
|
||||
return (
|
||||
<div
|
||||
className="position-relative zindex-0"
|
||||
className="d-flex flex-column position-relative zindex-0"
|
||||
style={{ minHeight: '100%' }}
|
||||
>
|
||||
<BaseModal
|
||||
size="md"
|
||||
@@ -64,7 +65,7 @@ export const EditorContainer = ({
|
||||
/>
|
||||
</div>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body className="pb-6">
|
||||
<ModalDialog.Body className="pb-0 mb-6">
|
||||
{isInitialized && children}
|
||||
</ModalDialog.Body>
|
||||
<EditorFooter
|
||||
|
||||
@@ -32,7 +32,7 @@ export const VideoPreviewWidget = ({
|
||||
<div className="d-flex flex-row">
|
||||
<Image
|
||||
thumbnail
|
||||
className="mr-3 p-4"
|
||||
className="mr-3 px-6 py-4.5"
|
||||
ref={imgRef}
|
||||
src={thumbnailImage}
|
||||
alt={intl.formatMessage(thumbnailMessages.thumbnailAltText)}
|
||||
|
||||
@@ -137,10 +137,14 @@ export const useVideoListProps = ({
|
||||
};
|
||||
};
|
||||
|
||||
export const useVideoUploadHandler = () => {
|
||||
export const useVideoUploadHandler = ({ replace }) => {
|
||||
const learningContextId = useSelector(selectors.app.learningContextId);
|
||||
const blockId = useSelector(selectors.app.blockId);
|
||||
return () => navigateTo(`/course/${learningContextId}/editor/video_upload/${blockId}`);
|
||||
const path = `/course/${learningContextId}/editor/video_upload/${blockId}`;
|
||||
if (replace) {
|
||||
return () => window.location.replace(path);
|
||||
}
|
||||
return () => navigateTo(path);
|
||||
};
|
||||
|
||||
export const useCancelHandler = () => (
|
||||
@@ -196,7 +200,7 @@ export const useVideoProps = ({ videos }) => {
|
||||
inputError,
|
||||
selectBtnProps,
|
||||
} = videoList;
|
||||
const fileInput = { click: useVideoUploadHandler() };
|
||||
const fileInput = { click: useVideoUploadHandler({ replace: false }) };
|
||||
|
||||
return {
|
||||
galleryError,
|
||||
|
||||
@@ -19,7 +19,7 @@ export const VideoGallery = () => {
|
||||
(state) => selectors.requests.isFailed(state, { requestKey: RequestKeys.uploadVideo }),
|
||||
);
|
||||
const videos = hooks.buildVideos({ rawVideos });
|
||||
const handleVideoUpload = hooks.useVideoUploadHandler();
|
||||
const handleVideoUpload = hooks.useVideoUploadHandler({ replace: true });
|
||||
|
||||
useEffect(() => {
|
||||
// If no videos exists redirects to the video upload screen
|
||||
|
||||
@@ -80,7 +80,7 @@ describe('VideoGallery', () => {
|
||||
beforeAll(() => {
|
||||
oldLocation = window.location;
|
||||
delete window.location;
|
||||
window.location = { assign: jest.fn() };
|
||||
window.location = { replace: jest.fn() };
|
||||
});
|
||||
afterAll(() => {
|
||||
window.location = oldLocation;
|
||||
@@ -118,10 +118,10 @@ describe('VideoGallery', () => {
|
||||
));
|
||||
});
|
||||
it('navigates to video upload page when there are no videos', async () => {
|
||||
expect(window.location.assign).not.toHaveBeenCalled();
|
||||
expect(window.location.replace).not.toHaveBeenCalled();
|
||||
updateState({ videos: [] });
|
||||
await renderComponent();
|
||||
expect(window.location.assign).toHaveBeenCalled();
|
||||
expect(window.location.replace).toHaveBeenCalled();
|
||||
});
|
||||
it.each([
|
||||
[/newest/i, [2, 1, 3]],
|
||||
|
||||
@@ -8,7 +8,6 @@ import { ArrowForward, FileUpload, Close } from '@edx/paragon/icons';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { thunkActions } from '../../data/redux';
|
||||
import * as hooks from './hooks';
|
||||
import * as editorHooks from '../EditorContainer/hooks';
|
||||
import messages from './messages';
|
||||
|
||||
const URLUploader = () => {
|
||||
@@ -17,49 +16,52 @@ const URLUploader = () => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<div className="d-flex flex-column">
|
||||
<div style={{ backgroundColor: '#F2F0EF' }} className="justify-content-center align-self-center rounded-circle p-5">
|
||||
<Icon src={FileUpload} className="text-muted" size="lg" />
|
||||
<div className="justify-content-center align-self-center rounded-circle bg-light-300 p-2.5">
|
||||
<Icon src={FileUpload} className="text-muted" style={{ height: '2rem', width: '2rem' }} />
|
||||
</div>
|
||||
<div className="d-flex align-self-center justify-content-center flex-wrap flex-column pt-5">
|
||||
<span className="small">{intl.formatMessage(messages.dropVideoFileHere)}</span>
|
||||
<span className="align-self-center" style={{ fontSize: '0.8rem' }}>{intl.formatMessage(messages.info)}</span>
|
||||
<div className="d-flex align-self-center justify-content-center flex-wrap flex-column pt-3">
|
||||
<span>{intl.formatMessage(messages.dropVideoFileHere)}</span>
|
||||
<span className="x-small align-self-center pt-2">{intl.formatMessage(messages.info)}</span>
|
||||
</div>
|
||||
<div className="x-small align-self-center justify-content-center mx-2 text-dark font-weight-normal">OR</div>
|
||||
<div className="zindex-9 video-id-prompt p-4">
|
||||
<InputGroup className="video-upload-input-group">
|
||||
<div className="small align-self-center justify-content-center mx-2 text-dark font-weight-normal pt-3">
|
||||
OR
|
||||
</div>
|
||||
<div className="zindex-9 video-id-prompt py-3">
|
||||
<InputGroup>
|
||||
<FormControl
|
||||
className="m-0"
|
||||
placeholder={intl.formatMessage(messages.pasteURL)}
|
||||
aria-label={intl.formatMessage(messages.pasteURL)}
|
||||
aria-describedby="basic-addon2"
|
||||
borderless
|
||||
onClick={(event) => { event.stopPropagation(); }}
|
||||
onChange={(event) => { setTextInputValue(event.target.value); }}
|
||||
trailingElement={(
|
||||
<IconButton
|
||||
className="url-submit-button"
|
||||
alt={intl.formatMessage(messages.submitButtonAltText)}
|
||||
src={ArrowForward}
|
||||
iconAs={Icon}
|
||||
size="inline"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
if (textInputValue.trim() !== '') {
|
||||
onURLUpload(textInputValue);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<div className="light-300 justify-content-center align-self-center bg-light rounded-circle p-0 x-small url-submit-button">
|
||||
<IconButton
|
||||
className="text-muted"
|
||||
alt={intl.formatMessage(messages.submitButtonAltText)}
|
||||
src={ArrowForward}
|
||||
iconAs={Icon}
|
||||
size="inline"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
if (textInputValue.trim() !== '') {
|
||||
onURLUpload(textInputValue);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</InputGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const VideoUploader = ({ setLoading, onClose }) => {
|
||||
export const VideoUploader = ({ setLoading }) => {
|
||||
const dispatch = useDispatch();
|
||||
const intl = useIntl();
|
||||
const handleCancel = editorHooks.handleCancel({ onClose });
|
||||
const goBack = hooks.useHistoryGoBack();
|
||||
|
||||
const handleProcessUpload = ({ fileData }) => {
|
||||
dispatch(thunkActions.video.uploadVideo({
|
||||
@@ -77,7 +79,7 @@ export const VideoUploader = ({ setLoading, onClose }) => {
|
||||
alt={intl.formatMessage(messages.closeButtonAltText)}
|
||||
src={Close}
|
||||
iconAs={Icon}
|
||||
onClick={handleCancel}
|
||||
onClick={goBack}
|
||||
/>
|
||||
</div>
|
||||
<Dropzone
|
||||
@@ -91,7 +93,6 @@ export const VideoUploader = ({ setLoading, onClose }) => {
|
||||
|
||||
VideoUploader.propTypes = {
|
||||
setLoading: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default VideoUploader;
|
||||
|
||||
@@ -60,11 +60,11 @@ Object {
|
||||
class="d-flex flex-column"
|
||||
>
|
||||
<div
|
||||
class="justify-content-center align-self-center rounded-circle p-5"
|
||||
style="background-color: rgb(242, 240, 239);"
|
||||
class="justify-content-center align-self-center rounded-circle bg-light-300 p-2.5"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon pgn__icon__lg text-muted"
|
||||
class="pgn__icon text-muted"
|
||||
style="height: 2rem; width: 2rem;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
@@ -84,33 +84,30 @@ Object {
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-self-center justify-content-center flex-wrap flex-column pt-5"
|
||||
class="d-flex align-self-center justify-content-center flex-wrap flex-column pt-3"
|
||||
>
|
||||
<span
|
||||
class="small"
|
||||
>
|
||||
<span>
|
||||
Drag and drop video here or click to upload
|
||||
</span>
|
||||
<span
|
||||
class="align-self-center"
|
||||
style="font-size: 0.8rem;"
|
||||
class="x-small align-self-center pt-2"
|
||||
>
|
||||
Upload MP4 or MOV files (5 GB max)
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="x-small align-self-center justify-content-center mx-2 text-dark font-weight-normal"
|
||||
class="small align-self-center justify-content-center mx-2 text-dark font-weight-normal pt-3"
|
||||
>
|
||||
OR
|
||||
</div>
|
||||
<div
|
||||
class="zindex-9 video-id-prompt p-4"
|
||||
class="zindex-9 video-id-prompt py-3"
|
||||
>
|
||||
<div
|
||||
class="video-upload-input-group input-group"
|
||||
class="input-group"
|
||||
>
|
||||
<div
|
||||
class="pgn__form-control-decorator-group"
|
||||
class="pgn__form-control-decorator-group has-appended-node has-trailing-element m-0"
|
||||
>
|
||||
<input
|
||||
aria-describedby="basic-addon2"
|
||||
@@ -119,39 +116,39 @@ Object {
|
||||
placeholder="Paste your video ID or URL"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="light-300 justify-content-center align-self-center bg-light rounded-circle p-0 x-small url-submit-button"
|
||||
>
|
||||
<button
|
||||
aria-label="Submit"
|
||||
class="btn-icon btn-icon-primary btn-icon-inline text-muted"
|
||||
type="button"
|
||||
<div
|
||||
class="pgn__form-control-decorator pgn__form-control-decorator-trailing"
|
||||
>
|
||||
<span
|
||||
class="btn-icon__icon-container"
|
||||
<button
|
||||
aria-label="Submit"
|
||||
class="btn-icon btn-icon-primary btn-icon-inline url-submit-button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon btn-icon__icon"
|
||||
class="btn-icon__icon-container"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<span
|
||||
class="pgn__icon btn-icon__icon"
|
||||
>
|
||||
<path
|
||||
d="m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -218,11 +215,11 @@ Object {
|
||||
class="d-flex flex-column"
|
||||
>
|
||||
<div
|
||||
class="justify-content-center align-self-center rounded-circle p-5"
|
||||
style="background-color: rgb(242, 240, 239);"
|
||||
class="justify-content-center align-self-center rounded-circle bg-light-300 p-2.5"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon pgn__icon__lg text-muted"
|
||||
class="pgn__icon text-muted"
|
||||
style="height: 2rem; width: 2rem;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
@@ -242,33 +239,30 @@ Object {
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-self-center justify-content-center flex-wrap flex-column pt-5"
|
||||
class="d-flex align-self-center justify-content-center flex-wrap flex-column pt-3"
|
||||
>
|
||||
<span
|
||||
class="small"
|
||||
>
|
||||
<span>
|
||||
Drag and drop video here or click to upload
|
||||
</span>
|
||||
<span
|
||||
class="align-self-center"
|
||||
style="font-size: 0.8rem;"
|
||||
class="x-small align-self-center pt-2"
|
||||
>
|
||||
Upload MP4 or MOV files (5 GB max)
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="x-small align-self-center justify-content-center mx-2 text-dark font-weight-normal"
|
||||
class="small align-self-center justify-content-center mx-2 text-dark font-weight-normal pt-3"
|
||||
>
|
||||
OR
|
||||
</div>
|
||||
<div
|
||||
class="zindex-9 video-id-prompt p-4"
|
||||
class="zindex-9 video-id-prompt py-3"
|
||||
>
|
||||
<div
|
||||
class="video-upload-input-group input-group"
|
||||
class="input-group"
|
||||
>
|
||||
<div
|
||||
class="pgn__form-control-decorator-group"
|
||||
class="pgn__form-control-decorator-group has-appended-node has-trailing-element m-0"
|
||||
>
|
||||
<input
|
||||
aria-describedby="basic-addon2"
|
||||
@@ -277,39 +271,39 @@ Object {
|
||||
placeholder="Paste your video ID or URL"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="light-300 justify-content-center align-self-center bg-light rounded-circle p-0 x-small url-submit-button"
|
||||
>
|
||||
<button
|
||||
aria-label="Submit"
|
||||
class="btn-icon btn-icon-primary btn-icon-inline text-muted"
|
||||
type="button"
|
||||
<div
|
||||
class="pgn__form-control-decorator pgn__form-control-decorator-trailing"
|
||||
>
|
||||
<span
|
||||
class="btn-icon__icon-container"
|
||||
<button
|
||||
aria-label="Submit"
|
||||
class="btn-icon btn-icon-primary btn-icon-inline url-submit-button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon btn-icon__icon"
|
||||
class="btn-icon__icon-container"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<span
|
||||
class="pgn__icon btn-icon__icon"
|
||||
>
|
||||
<path
|
||||
d="m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,171 +4,6 @@ exports[`VideoUploadEditor renders as expected with default behavior 1`] = `
|
||||
Object {
|
||||
"asFragment": [Function],
|
||||
"baseElement": <body>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
class="d-flex marked-area flex-column p-3"
|
||||
>
|
||||
<div
|
||||
class="d-flex flex-column"
|
||||
>
|
||||
<div
|
||||
class="d-flex justify-content-end flex-row"
|
||||
>
|
||||
<button
|
||||
aria-label="Close"
|
||||
class="btn-icon btn-icon-primary btn-icon-md position-absolute mr-2 mt-2"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="btn-icon__icon-container"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon btn-icon__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="pgn__dropzone"
|
||||
data-testid="dropzone-container"
|
||||
role="presentation"
|
||||
tabindex="0"
|
||||
>
|
||||
<input
|
||||
accept="video/*,.mp4,.mov"
|
||||
style="display: none;"
|
||||
tabindex="-1"
|
||||
type="file"
|
||||
/>
|
||||
<div
|
||||
class="d-flex flex-column justify-content-around align-items-center w-100"
|
||||
>
|
||||
<div
|
||||
class="d-flex flex-column"
|
||||
>
|
||||
<div
|
||||
class="justify-content-center align-self-center rounded-circle p-5"
|
||||
style="background-color: rgb(242, 240, 239);"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon pgn__icon__lg text-muted"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M5 10h4v6h6v-6h4l-7-7-7 7zm0 8v2h14v-2H5z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-self-center justify-content-center flex-wrap flex-column pt-5"
|
||||
>
|
||||
<span
|
||||
class="small"
|
||||
>
|
||||
Drag and drop video here or click to upload
|
||||
</span>
|
||||
<span
|
||||
class="align-self-center"
|
||||
style="font-size: 0.8rem;"
|
||||
>
|
||||
Upload MP4 or MOV files (5 GB max)
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="x-small align-self-center justify-content-center mx-2 text-dark font-weight-normal"
|
||||
>
|
||||
OR
|
||||
</div>
|
||||
<div
|
||||
class="zindex-9 video-id-prompt p-4"
|
||||
>
|
||||
<div
|
||||
class="video-upload-input-group input-group"
|
||||
>
|
||||
<div
|
||||
class="pgn__form-control-decorator-group"
|
||||
>
|
||||
<input
|
||||
aria-describedby="basic-addon2"
|
||||
aria-label="Paste your video ID or URL"
|
||||
class="form-control"
|
||||
placeholder="Paste your video ID or URL"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="light-300 justify-content-center align-self-center bg-light rounded-circle p-0 x-small url-submit-button"
|
||||
>
|
||||
<button
|
||||
aria-label="Submit"
|
||||
class="btn-icon btn-icon-primary btn-icon-inline text-muted"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="btn-icon__icon-container"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon btn-icon__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
,
|
||||
</div>
|
||||
</body>,
|
||||
"container": <div>
|
||||
<div>
|
||||
<div
|
||||
class="d-flex marked-area flex-column p-3"
|
||||
@@ -228,11 +63,11 @@ Object {
|
||||
class="d-flex flex-column"
|
||||
>
|
||||
<div
|
||||
class="justify-content-center align-self-center rounded-circle p-5"
|
||||
style="background-color: rgb(242, 240, 239);"
|
||||
class="justify-content-center align-self-center rounded-circle bg-light-300 p-2.5"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon pgn__icon__lg text-muted"
|
||||
class="pgn__icon text-muted"
|
||||
style="height: 2rem; width: 2rem;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
@@ -252,33 +87,30 @@ Object {
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-self-center justify-content-center flex-wrap flex-column pt-5"
|
||||
class="d-flex align-self-center justify-content-center flex-wrap flex-column pt-3"
|
||||
>
|
||||
<span
|
||||
class="small"
|
||||
>
|
||||
<span>
|
||||
Drag and drop video here or click to upload
|
||||
</span>
|
||||
<span
|
||||
class="align-self-center"
|
||||
style="font-size: 0.8rem;"
|
||||
class="x-small align-self-center pt-2"
|
||||
>
|
||||
Upload MP4 or MOV files (5 GB max)
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="x-small align-self-center justify-content-center mx-2 text-dark font-weight-normal"
|
||||
class="small align-self-center justify-content-center mx-2 text-dark font-weight-normal pt-3"
|
||||
>
|
||||
OR
|
||||
</div>
|
||||
<div
|
||||
class="zindex-9 video-id-prompt p-4"
|
||||
class="zindex-9 video-id-prompt py-3"
|
||||
>
|
||||
<div
|
||||
class="video-upload-input-group input-group"
|
||||
class="input-group"
|
||||
>
|
||||
<div
|
||||
class="pgn__form-control-decorator-group"
|
||||
class="pgn__form-control-decorator-group has-appended-node has-trailing-element m-0"
|
||||
>
|
||||
<input
|
||||
aria-describedby="basic-addon2"
|
||||
@@ -287,13 +119,171 @@ Object {
|
||||
placeholder="Paste your video ID or URL"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
class="pgn__form-control-decorator pgn__form-control-decorator-trailing"
|
||||
>
|
||||
<button
|
||||
aria-label="Submit"
|
||||
class="btn-icon btn-icon-primary btn-icon-inline url-submit-button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="btn-icon__icon-container"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon btn-icon__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
,
|
||||
</div>
|
||||
</body>,
|
||||
"container": <div>
|
||||
<div
|
||||
class="d-flex marked-area flex-column p-3"
|
||||
>
|
||||
<div
|
||||
class="d-flex flex-column"
|
||||
>
|
||||
<div
|
||||
class="d-flex justify-content-end flex-row"
|
||||
>
|
||||
<button
|
||||
aria-label="Close"
|
||||
class="btn-icon btn-icon-primary btn-icon-md position-absolute mr-2 mt-2"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="btn-icon__icon-container"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon btn-icon__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="pgn__dropzone"
|
||||
data-testid="dropzone-container"
|
||||
role="presentation"
|
||||
tabindex="0"
|
||||
>
|
||||
<input
|
||||
accept="video/*,.mp4,.mov"
|
||||
style="display: none;"
|
||||
tabindex="-1"
|
||||
type="file"
|
||||
/>
|
||||
<div
|
||||
class="d-flex flex-column justify-content-around align-items-center w-100"
|
||||
>
|
||||
<div
|
||||
class="d-flex flex-column"
|
||||
>
|
||||
<div
|
||||
class="justify-content-center align-self-center rounded-circle bg-light-300 p-2.5"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon text-muted"
|
||||
style="height: 2rem; width: 2rem;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M5 10h4v6h6v-6h4l-7-7-7 7zm0 8v2h14v-2H5z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-self-center justify-content-center flex-wrap flex-column pt-3"
|
||||
>
|
||||
<span>
|
||||
Drag and drop video here or click to upload
|
||||
</span>
|
||||
<span
|
||||
class="x-small align-self-center pt-2"
|
||||
>
|
||||
Upload MP4 or MOV files (5 GB max)
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="small align-self-center justify-content-center mx-2 text-dark font-weight-normal pt-3"
|
||||
>
|
||||
OR
|
||||
</div>
|
||||
<div
|
||||
class="zindex-9 video-id-prompt py-3"
|
||||
>
|
||||
<div
|
||||
class="input-group"
|
||||
>
|
||||
<div
|
||||
class="pgn__form-control-decorator-group has-appended-node has-trailing-element m-0"
|
||||
>
|
||||
<input
|
||||
aria-describedby="basic-addon2"
|
||||
aria-label="Paste your video ID or URL"
|
||||
class="form-control"
|
||||
placeholder="Paste your video ID or URL"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
class="light-300 justify-content-center align-self-center bg-light rounded-circle p-0 x-small url-submit-button"
|
||||
class="pgn__form-control-decorator pgn__form-control-decorator-trailing"
|
||||
>
|
||||
<button
|
||||
aria-label="Submit"
|
||||
class="btn-icon btn-icon-primary btn-icon-inline text-muted"
|
||||
class="btn-icon btn-icon-primary btn-icon-inline url-submit-button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
|
||||
@@ -31,8 +31,11 @@ export const useUploadVideo = async ({
|
||||
}));
|
||||
};
|
||||
|
||||
export const useHistoryGoBack = () => (() => window.history.back());
|
||||
|
||||
export default {
|
||||
postUploadRedirect,
|
||||
onVideoUpload,
|
||||
useUploadVideo,
|
||||
useHistoryGoBack,
|
||||
};
|
||||
|
||||
@@ -1,40 +1,33 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Spinner } from '@edx/paragon';
|
||||
import './index.scss';
|
||||
import messages from './messages';
|
||||
import { VideoUploader } from './VideoUploader';
|
||||
|
||||
export const VideoUploadEditor = (
|
||||
{
|
||||
onClose,
|
||||
},
|
||||
) => {
|
||||
export const VideoUploadEditor = () => {
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{(!loading) ? (
|
||||
<div className="d-flex marked-area flex-column p-3">
|
||||
<VideoUploader setLoading={setLoading} onClose={onClose} />
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center p-6">
|
||||
<Spinner
|
||||
animation="border"
|
||||
className="m-3"
|
||||
screenreadertext={intl.formatMessage(messages.spinnerScreenReaderText)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
return (!loading) ? (
|
||||
<div className="d-flex marked-area flex-column p-3">
|
||||
<VideoUploader setLoading={setLoading} />
|
||||
</div>
|
||||
) : (
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
left: '50%',
|
||||
top: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
}}
|
||||
>
|
||||
<Spinner
|
||||
animation="border"
|
||||
className="m-3"
|
||||
screenreadertext={intl.formatMessage(messages.spinnerScreenReaderText)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
VideoUploadEditor.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default VideoUploadEditor;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@import "@edx/paragon/scss/core/core";
|
||||
|
||||
.dropzone-middle {
|
||||
border: 2px dashed #ccc;
|
||||
|
||||
@@ -11,12 +13,6 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.url-submit-button {
|
||||
position: absolute;
|
||||
margin-left: 17rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.video-id-prompt {
|
||||
|
||||
input::placeholder {
|
||||
@@ -24,7 +20,6 @@
|
||||
// color: #5E35B1;
|
||||
font-weight: '500';
|
||||
word-wrap: 'break-word';
|
||||
font-size: 0.875rem !important;
|
||||
}
|
||||
|
||||
button {
|
||||
@@ -32,21 +27,15 @@
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.btn-icon.url-submit-button {
|
||||
&, &:active, &:hover {
|
||||
background-color: transparent !important;
|
||||
border: none !important;
|
||||
color: $gray-500 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.prompt-button {
|
||||
background: rgba(239, 234, 247, 0.70);
|
||||
}
|
||||
}
|
||||
|
||||
.video-upload-input-group{
|
||||
.form-control {
|
||||
font-size: 0.875rem !important;
|
||||
width: 308px !important;
|
||||
height: 44px !important;
|
||||
}
|
||||
|
||||
.pgn__icon.pgn__icon__lg {
|
||||
width: 3.625rem !important;
|
||||
height: 3.625rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,12 @@ jest.unmock('@edx/paragon');
|
||||
jest.unmock('@edx/paragon/icons');
|
||||
|
||||
describe('VideoUploadEditor', () => {
|
||||
const onCloseMock = jest.fn();
|
||||
let store;
|
||||
|
||||
const renderComponent = async (storeParam, onCloseMockParam) => render(
|
||||
const renderComponent = async (storeParam) => render(
|
||||
<AppProvider store={storeParam}>
|
||||
<IntlProvider locale="en">
|
||||
<VideoUploadEditor onClose={onCloseMockParam} />
|
||||
<VideoUploadEditor />
|
||||
</IntlProvider>,
|
||||
</AppProvider>,
|
||||
);
|
||||
@@ -45,14 +44,20 @@ describe('VideoUploadEditor', () => {
|
||||
});
|
||||
|
||||
it('renders as expected with default behavior', async () => {
|
||||
expect(await renderComponent(store, onCloseMock)).toMatchSnapshot();
|
||||
expect(await renderComponent(store)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('calls onClose when close button is clicked', async () => {
|
||||
const container = await renderComponent(store, onCloseMock);
|
||||
it('calls window.history.back when close button is clicked', async () => {
|
||||
const container = await renderComponent(store);
|
||||
const closeButton = container.getAllByRole('button', { name: /close/i });
|
||||
const oldHistoryBack = window.history.back;
|
||||
window.history.back = jest.fn();
|
||||
|
||||
expect(closeButton).toHaveLength(1);
|
||||
expect(window.history.back).not.toHaveBeenCalled();
|
||||
closeButton.forEach((button) => fireEvent.click(button));
|
||||
expect(onCloseMock).toHaveBeenCalled();
|
||||
expect(window.history.back).toHaveBeenCalled();
|
||||
|
||||
window.history.back = oldHistoryBack;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.4111 10.6847V21.3514H7.0778V10.6847H20.4111ZM21.7445 8.01807H5.74447C5.01113 8.01807 4.41113 8.61807 4.41113 9.3514V22.6847C4.41113 23.4181 5.01113 24.0181 5.74447 24.0181H21.7445C22.4778 24.0181 23.0778 23.4181 23.0778 22.6847V18.0181L28.4111 23.3514V8.68473L23.0778 14.0181V9.3514C23.0778 8.61807 22.4778 8.01807 21.7445 8.01807Z" fill="black"/>
|
||||
<path d="M20.4111 10.6847V21.3514H7.0778V10.6847H20.4111ZM21.7445 8.01807H5.74447C5.01113 8.01807 4.41113 8.61807 4.41113 9.3514V22.6847C4.41113 23.4181 5.01113 24.0181 5.74447 24.0181H21.7445C22.4778 24.0181 23.0778 23.4181 23.0778 22.6847V18.0181L28.4111 23.3514V8.68473L23.0778 14.0181V9.3514C23.0778 8.61807 22.4778 8.01807 21.7445 8.01807Z" fill="#707070"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 464 B After Width: | Height: | Size: 466 B |
Reference in New Issue
Block a user