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:
Artur Gaspar
2023-12-04 11:58:17 -03:00
committed by GitHub
parent 2aeb094315
commit 1ddaf9a662
16 changed files with 378 additions and 360 deletions

View File

@@ -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}
>

View File

@@ -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

View File

@@ -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}

View File

@@ -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

View File

@@ -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)}

View File

@@ -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,

View File

@@ -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

View File

@@ -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]],

View File

@@ -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;

View File

@@ -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>

View File

@@ -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

View File

@@ -31,8 +31,11 @@ export const useUploadVideo = async ({
}));
};
export const useHistoryGoBack = () => (() => window.history.back());
export default {
postUploadRedirect,
onVideoUpload,
useUploadVideo,
useHistoryGoBack,
};

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;
});
});

View File

@@ -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