Skip to content

Commit

Permalink
Merge branch 'master' into Peter_Kulko/copy-paste-functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
ihor-romaniuk authored Apr 17, 2024
2 parents 7cb96ce + 612d1d8 commit 2c1864e
Show file tree
Hide file tree
Showing 30 changed files with 1,098 additions and 200 deletions.
3 changes: 2 additions & 1 deletion .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ ENABLE_TEAM_TYPE_SETTING=false
ENABLE_NEW_EDITOR_PAGES=true
ENABLE_UNIT_PAGE=false
ENABLE_ASSETS_PAGE=false
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN=false
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN=true
ENABLE_NEW_VIDEO_UPLOAD_PAGE=true
ENABLE_TAGGING_TAXONOMY_PAGES=true
BBB_LEARN_MORE_URL=''
HOTJAR_APP_ID=''
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
node-version: ${{ env.NODE_VER }}
- run: make validate.ci
- name: Upload coverage
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: false
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
16 changes: 16 additions & 0 deletions src/course-outline/CourseOutline.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,19 @@
@import "./configure-modal/ConfigureModal";
@import "./drag-helper/SortableItem";
@import "./xblock-status/XBlockStatus";
@import "./paste-button/PasteButton";

div.row:has(> div > div.highlight) {
animation: 5s glow;
animation-timing-function: cubic-bezier(1, 0, .72, .04);
}

@keyframes glow {
0% {
box-shadow: 0 0 5px 5px $primary-500;
}

100% {
box-shadow: unset;
}
}
11 changes: 7 additions & 4 deletions src/course-outline/section-card/SectionCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useDispatch } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Bubble, Button, useToggle } from '@openedx/paragon';
import { Add as IconAdd } from '@openedx/paragon/icons';
import { useSearchParams } from 'react-router-dom';
import classNames from 'classnames';

import { setCurrentItem, setCurrentSection } from '../data/slice';
Expand Down Expand Up @@ -42,6 +43,9 @@ const SectionCard = ({
const dispatch = useDispatch();
const { activeId, overId } = useContext(DragContext);
const [isExpanded, setIsExpanded] = useState(isSectionsExpanded);
const [searchParams] = useSearchParams();
const locatorId = searchParams.get('show');
const isScrolledToElement = locatorId === section.id;
const [isFormOpen, openForm, closeForm] = useToggle(false);
const namePrefix = 'section';

Expand Down Expand Up @@ -70,11 +74,10 @@ const SectionCard = ({
}, [activeId, overId]);

useEffect(() => {
// if this items has been newly added, scroll to it.
if (currentRef.current && section.shouldScroll) {
if (currentRef.current && (section.shouldScroll || isScrolledToElement)) {
scrollToElement(currentRef.current);
}
}, []);
}, [isScrolledToElement]);

// re-create actions object for customizations
const actions = { ...sectionActions };
Expand Down Expand Up @@ -155,7 +158,7 @@ const SectionCard = ({
}}
>
<div
className="section-card"
className={`section-card ${isScrolledToElement ? 'highlight' : ''}`}
data-testid="section-card"
ref={currentRef}
>
Expand Down
8 changes: 6 additions & 2 deletions src/course-outline/subsection-card/SubsectionCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ const SubsectionCard = ({
if (currentRef.current && (section.shouldScroll || subsection.shouldScroll || isScrolledToElement)) {
scrollToElement(currentRef.current);
}
}, []);
}, [isScrolledToElement]);

useEffect(() => {
if (savingStatus === RequestStatus.SUCCESSFUL) {
Expand All @@ -160,7 +160,11 @@ const SubsectionCard = ({
...borderStyle,
}}
>
<div className="subsection-card" data-testid="subsection-card" ref={currentRef}>
<div
className={`subsection-card ${isScrolledToElement ? 'highlight' : ''}`}
data-testid="subsection-card"
ref={currentRef}
>
{isHeaderVisible && (
<>
<CardHeader
Expand Down
10 changes: 7 additions & 3 deletions src/course-outline/unit-card/UnitCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
import { useToggle } from '@openedx/paragon';
import { isEmpty } from 'lodash';
import { useSearchParams } from 'react-router-dom';

import { setCurrentItem, setCurrentSection, setCurrentSubsection } from '../data/slice';
import { RequestStatus } from '../../data/constants';
Expand Down Expand Up @@ -34,6 +35,9 @@ const UnitCard = ({
}) => {
const currentRef = useRef(null);
const dispatch = useDispatch();
const [searchParams] = useSearchParams();
const locatorId = searchParams.get('show');
const isScrolledToElement = locatorId === unit.id;
const [isFormOpen, openForm, closeForm] = useToggle(false);
const namePrefix = 'unit';

Expand Down Expand Up @@ -109,10 +113,10 @@ const UnitCard = ({
// if this items has been newly added, scroll to it.
// we need to check section.shouldScroll as whole section is fetched when a
// unit is duplicated under it.
if (currentRef.current && (section.shouldScroll || unit.shouldScroll)) {
if (currentRef.current && (section.shouldScroll || unit.shouldScroll || isScrolledToElement)) {
scrollToElement(currentRef.current);
}
}, []);
}, [isScrolledToElement]);

useEffect(() => {
if (savingStatus === RequestStatus.SUCCESSFUL) {
Expand All @@ -139,7 +143,7 @@ const UnitCard = ({
}}
>
<div
className="unit-card"
className={`unit-card ${isScrolledToElement ? 'highlight' : ''}`}
data-testid="unit-card"
ref={currentRef}
>
Expand Down
4 changes: 4 additions & 0 deletions src/custom.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module '*.svg' {
const content: string;
export default content;
}
4 changes: 4 additions & 0 deletions src/files-and-videos/generic/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ const messages = defineMessages({
defaultMessage: 'Apply',
description: 'Label for apply sort button in sort and filter modal',
},
failedLabel: {
id: 'course-authoring.files-and-uploads.filter.failed.label',
defaultMessage: 'Failed',
},
});

export default messages;
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import React from 'react';
import { PropTypes } from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Badge } from '@openedx/paragon';
import { VIDEO_FAILURE_STATUSES } from '../../../videos-page/data/constants';
import messages from '../../messages';

const StatusColumn = ({ row }) => {
const { status } = row.original;
const isUploaded = status === 'Success';
const isFailed = VIDEO_FAILURE_STATUSES.includes(status);
const intl = useIntl();
const failedText = intl.formatMessage(messages.failedLabel);

if (isUploaded) {
return null;
}

return (
<Badge variant="light">
{status}
{isFailed ? failedText : status}
</Badge>
);
};
Expand Down
9 changes: 9 additions & 0 deletions src/files-and-videos/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,12 @@
gap: 24px 16px;
grid-template-columns: repeat(3, 33%);
}

.video-upload-spinner {
width: 1.3rem;
height: 1.3rem;
}

.video-upload-warning-text {
font-size: 18px;
}
6 changes: 4 additions & 2 deletions src/files-and-videos/videos-page/VideoThumbnail.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '@openedx/paragon';
import { FileInput, useFileInput } from '../generic';
import messages from './messages';
import { VIDEO_SUCCESS_STATUSES } from './data/constants';
import { VIDEO_SUCCESS_STATUSES, VIDEO_FAILURE_STATUSES } from './data/constants';
import { RequestStatus } from '../../data/constants';

const VideoThumbnail = ({
Expand Down Expand Up @@ -45,6 +45,8 @@ const VideoThumbnail = ({
const supportedFiles = videoImageSettings?.supportedFileFormats
? Object.values(videoImageSettings.supportedFileFormats) : null;
const isUploaded = VIDEO_SUCCESS_STATUSES.includes(status);
const isFailed = VIDEO_FAILURE_STATUSES.includes(status);
const failedMessage = intl.formatMessage(messages.failedCheckboxLabel);

const showThumbnail = allowThumbnailUpload && thumbnail && isUploaded;

Expand Down Expand Up @@ -84,7 +86,7 @@ const VideoThumbnail = ({
<div className="status-badge">
{!isUploaded && (
<Badge variant="light">
{status}
{!isFailed ? status : failedMessage}
</Badge>
)}
</div>
Expand Down
48 changes: 40 additions & 8 deletions src/files-and-videos/videos-page/VideosPage.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect } from 'react';
import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import {
Expand All @@ -12,6 +12,8 @@ import {
Button,
CheckboxFilter,
Container,
Alert,
Spinner,
} from '@openedx/paragon';
import Placeholder from '@edx/frontend-lib-content-components';

Expand All @@ -24,6 +26,7 @@ import {
fetchVideoDownload,
fetchVideos,
getUsagePaths,
markVideoUploadsInProgressAsFailed,
resetErrors,
updateVideoOrder,
} from './data/thunks';
Expand All @@ -50,9 +53,16 @@ const VideosPage = ({
intl,
}) => {
const dispatch = useDispatch();
const [isTranscriptSettingsOpen, openTranscriptSettings, closeTranscriptSettings] = useToggle(false);
const [
isTranscriptSettingsOpen,
openTranscriptSettings,
closeTranscriptSettings,
] = useToggle(false);
const courseDetails = useModel('courseDetails', courseId);
document.title = getPageHeadTitle(courseDetails?.name, intl.formatMessage(messages.heading));
document.title = getPageHeadTitle(
courseDetails?.name,
intl.formatMessage(messages.heading),
);

useEffect(() => {
dispatch(fetchVideos(courseId));
Expand All @@ -68,7 +78,16 @@ const VideosPage = ({
usageStatus: usagePathStatus,
errors: errorMessages,
pageSettings,
} = useSelector(state => state.videos);
} = useSelector((state) => state.videos);

const uploadingIdsRef = useRef([]);

useEffect(() => {
window.onbeforeunload = () => {
dispatch(markVideoUploadsInProgressAsFailed({ uploadingIdsRef, courseId }));
return undefined;
};
}, []);

const {
isVideoTranscriptEnabled,
Expand All @@ -78,12 +97,14 @@ const VideosPage = ({
videoImageSettings,
} = pageSettings;

const supportedFileFormats = { 'video/*': videoSupportedFileFormats || FILES_AND_UPLOAD_TYPE_FILTERS.video };
const supportedFileFormats = {
'video/*': videoSupportedFileFormats || FILES_AND_UPLOAD_TYPE_FILTERS.video,
};

const handleErrorReset = (error) => dispatch(resetErrors(error));
const handleAddFile = (files) => {
handleErrorReset({ errorType: 'add' });
files.forEach(file => dispatch(addVideoFile(courseId, file, videoIds)));
files.forEach((file) => dispatch(addVideoFile(courseId, file, videoIds, uploadingIdsRef)));
};
const handleDeleteFile = (id) => dispatch(deleteVideoFile(courseId, id));
const handleDownloadFile = (selectedRows) => dispatch(fetchVideoDownload({ selectedRows, courseId }));
Expand Down Expand Up @@ -128,8 +149,14 @@ const VideosPage = ({
Filter: CheckboxFilter,
filter: 'exactTextCase',
filterChoices: [
{ name: intl.formatMessage(messages.transcribedCheckboxLabel), value: 'transcribed' },
{ name: intl.formatMessage(messages.notTranscribedCheckboxLabel), value: 'notTranscribed' },
{
name: intl.formatMessage(messages.transcribedCheckboxLabel),
value: 'transcribed',
},
{
name: intl.formatMessage(messages.notTranscribedCheckboxLabel),
value: 'notTranscribed',
},
],
};
const activeColumn = {
Expand Down Expand Up @@ -201,6 +228,11 @@ const VideosPage = ({
updateFileStatus={updateVideoStatus}
loadingStatus={loadingStatus}
/>
<Alert variant="warning" show={addVideoStatus === RequestStatus.IN_PROGRESS}>
<div className="video-upload-warning-text"><Spinner animation="border" variant="warning" className="video-upload-spinner mr-3" screenReaderText="loading" />
<p className="d-inline"><FormattedMessage {...messages.videoUploadAlertLabel} /></p>
</div>
</Alert>
<ActionRow>
<div className="h2">
<FormattedMessage {...messages.heading} />
Expand Down
Loading

0 comments on commit 2c1864e

Please sign in to comment.