Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions src/course-unit/CourseUnit.jsx → src/course-unit/CourseUnit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const CourseUnit = () => {
handleNavigateToTargetUnit,
addComponentTemplateData,
} = useCourseUnit({ courseId, blockId });

const layoutGrid = useLayoutGrid(unitCategory, isUnitLibraryType);

const readOnly = !!courseUnit.readOnly;
Expand Down Expand Up @@ -121,7 +122,7 @@ const CourseUnit = () => {
: intl.formatMessage(messages.alertMoveSuccessDescription, { title: movedXBlockParams.title })}
aria-hidden={movedXBlockParams.isSuccess}
dismissible
actions={movedXBlockParams.isUndo ? null : [
actions={movedXBlockParams.isUndo ? undefined : [
<Button
onClick={handleRollbackMovedXBlock}
key="xblock-moved-alert-undo-move-button"
Expand All @@ -146,7 +147,6 @@ const CourseUnit = () => {
{
link: (
<Alert.Link
className="ml-1"
href={courseUnit.upstreamInfo.upstreamLink}
>
{intl.formatMessage(messages.alertLibraryUnitReadOnlyLinkText)}
Expand Down Expand Up @@ -208,15 +208,17 @@ const CourseUnit = () => {
courseId={courseId}
/>
)}
<XBlockContainerIframe
courseId={courseId}
blockId={blockId}
isUnitVerticalType={isUnitVerticalType}
unitXBlockActions={unitXBlockActions}
courseVerticalChildren={courseVerticalChildren.children}
handleConfigureSubmit={handleConfigureSubmit}
/>
{!readOnly && (
{blockId && (
<XBlockContainerIframe
courseId={courseId}
blockId={blockId}
isUnitVerticalType={isUnitVerticalType}
unitXBlockActions={unitXBlockActions}
courseVerticalChildren={courseVerticalChildren.children}
handleConfigureSubmit={handleConfigureSubmit}
/>
)}
{!readOnly && blockId && (
<AddComponent
parentLocator={blockId}
isSplitTestType={isSplitTestType}
Expand All @@ -226,7 +228,7 @@ const CourseUnit = () => {
addComponentTemplateData={addComponentTemplateData}
/>
)}
{!readOnly && showPasteXBlock && canPasteComponent && isUnitVerticalType && (
{!readOnly && showPasteXBlock && canPasteComponent && isUnitVerticalType && sharedClipboardData && (
<PasteComponent
clipboardData={sharedClipboardData}
onClick={
Expand All @@ -244,15 +246,17 @@ const CourseUnit = () => {
<IframePreviewLibraryXBlockChanges />
</Layout.Element>
<Layout.Element>
<CourseAuthoringUnitSidebarSlot
courseId={courseId}
blockId={blockId}
unitTitle={unitTitle}
xBlocks={courseVerticalChildren.children}
readOnly={readOnly}
isUnitVerticalType={isUnitVerticalType}
isSplitTestType={isSplitTestType}
/>
{blockId && (
<CourseAuthoringUnitSidebarSlot
courseId={courseId}
blockId={blockId}
unitTitle={unitTitle}
xBlocks={courseVerticalChildren.children}
readOnly={readOnly}
isUnitVerticalType={isUnitVerticalType}
isSplitTestType={isSplitTestType}
/>
)}
</Layout.Element>
</Layout>
</section>
Expand Down
File renamed without changes.
101 changes: 95 additions & 6 deletions src/course-unit/header-title/HeaderTitle.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Form, IconButton, useToggle } from '@openedx/paragon';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
Badge, Form, Icon, IconButton, Stack, useToggle,
} from '@openedx/paragon';
import {
EditOutline as EditIcon,
Groups,
Lock,
QuestionAnswer,
Settings as SettingsIcon,
} from '@openedx/paragon/icons';

Expand All @@ -13,6 +18,90 @@
import { getCourseUnitData } from '../data/selectors';
import { updateQueryPendingStatus } from '../data/slice';
import messages from './messages';
import { UNIT_VISIBILITY_STATES } from '../constants';

const StatusBar = ({ courseUnit }) => {

Check failure on line 23 in src/course-unit/header-title/HeaderTitle.jsx

View workflow job for this annotation

GitHub Actions / tests

'courseUnit' is missing in props validation
const { selectedPartitionIndex, selectedGroupsLabel } = courseUnit.userPartitionInfo ?? {};

Check failure on line 24 in src/course-unit/header-title/HeaderTitle.jsx

View workflow job for this annotation

GitHub Actions / tests

'courseUnit.userPartitionInfo' is missing in props validation
const hasGroups = selectedPartitionIndex !== -1 && !Number.isNaN(selectedPartitionIndex) && selectedGroupsLabel;

let visibilityChipData = {
variant: 'success',
className: 'bg-white text-success-400 border border-success-500',
text: messages.statusBarUpcomingBadge,
};
let publishStatusChipData = {
variant: 'light',
className: '',
text: messages.statusBarUnpublishedBadge,
};

if (courseUnit.currentlyVisibleToStudents) {

Check failure on line 38 in src/course-unit/header-title/HeaderTitle.jsx

View workflow job for this annotation

GitHub Actions / tests

'courseUnit.currentlyVisibleToStudents' is missing in props validation
visibilityChipData = {
variant: 'success',
className: '',
text: messages.statusBarLiveBadge,
};
} else if (courseUnit.visibilityState === UNIT_VISIBILITY_STATES.ready) {

Check failure on line 44 in src/course-unit/header-title/HeaderTitle.jsx

View workflow job for this annotation

GitHub Actions / tests

'courseUnit.visibilityState' is missing in props validation
visibilityChipData = {
variant: 'success',
className: 'bg-white text-success-400 border border-success-500',
text: messages.statusBarReadyBadge,
};
}

if (courseUnit.published) {

Check failure on line 52 in src/course-unit/header-title/HeaderTitle.jsx

View workflow job for this annotation

GitHub Actions / tests

'courseUnit.published' is missing in props validation
if (courseUnit.hasChanges) {

Check failure on line 53 in src/course-unit/header-title/HeaderTitle.jsx

View workflow job for this annotation

GitHub Actions / tests

'courseUnit.hasChanges' is missing in props validation
publishStatusChipData = {
variant: 'warning',
className: 'bg-warning-500 text-primary-700 border border-warning-300',
text: messages.statusBarDraftChangesBadge,
};
} else {
publishStatusChipData = {
variant: 'success',
className: '',
text: messages.statusBarPublishedBadge,
};
}
}

return (
<Stack direction="horizontal" gap={3}>
<Badge
variant={visibilityChipData.variant}
className={`px-3 py-2 ${visibilityChipData.className}`}
>
<FormattedMessage {...visibilityChipData.text} />
</Badge>
<Badge
variant={publishStatusChipData.variant}
className={`px-3 py-2 ${publishStatusChipData.className}`}
>
<FormattedMessage {...publishStatusChipData.text} />
</Badge>
{courseUnit.visibilityState === UNIT_VISIBILITY_STATES.staffOnly && (

Check failure on line 82 in src/course-unit/header-title/HeaderTitle.jsx

View workflow job for this annotation

GitHub Actions / tests

'courseUnit.visibilityState' is missing in props validation
<Stack direction="horizontal" gap={1}>
<Icon src={Lock} />
<FormattedMessage {...messages.statusBarStaffOnly} />
</Stack>
)}
{hasGroups && (
<Stack direction="horizontal" gap={1}>
<Icon src={Groups} />
<span>
{selectedGroupsLabel}
</span>
</Stack>
)}
{courseUnit.discussionEnabled && (

Check failure on line 96 in src/course-unit/header-title/HeaderTitle.jsx

View workflow job for this annotation

GitHub Actions / tests

'courseUnit.discussionEnabled' is missing in props validation
<Stack direction="horizontal" gap={1}>
<Icon src={QuestionAnswer} />
<FormattedMessage {...messages.statusBarDiscussionsEnabled} />
</Stack>
)}
</Stack>
);
};

const HeaderTitle = ({
unitTitle,
Expand All @@ -26,7 +115,6 @@
const [titleValue, setTitleValue] = useState(unitTitle);
const currentItemData = useSelector(getCourseUnitData);
const [isConfigureModalOpen, openConfigureModal, closeConfigureModal] = useToggle(false);
const { selectedPartitionIndex, selectedGroupsLabel } = currentItemData.userPartitionInfo ?? {};

const isXBlockComponent = [
COURSE_BLOCK_NAMES.libraryContent.id,
Expand All @@ -41,9 +129,7 @@
const getVisibilityMessage = () => {
let message;

if (selectedPartitionIndex !== -1 && !Number.isNaN(selectedPartitionIndex) && selectedGroupsLabel) {
message = intl.formatMessage(messages.definedVisibilityMessage, { selectedGroupsLabel });
} else if (currentItemData.hasPartitionGroupComponents) {
if (currentItemData.hasPartitionGroupComponents) {
message = intl.formatMessage(messages.commonVisibilityMessage);
}

Expand Down Expand Up @@ -97,6 +183,9 @@
userPartitionInfo={currentItemData?.userPartitionInfo || {}}
/>
</div>
<div className="h5 font-weight-normal">
<StatusBar courseUnit={currentItemData} />
</div>
{getVisibilityMessage()}
</>
);
Expand Down
40 changes: 40 additions & 0 deletions src/course-unit/header-title/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,46 @@ const messages = defineMessages({
defaultMessage: 'Access to some content in this unit is restricted to specific groups of learners.',
description: 'The label text of some content restriction in this unit',
},
statusBarLiveBadge: {
id: 'course-authoring.course-unit.status-bar.visibility.chip',
defaultMessage: 'Live',
description: 'Text for the Live Badge in the status bar.',
},
statusBarReadyBadge: {
id: 'course-authoring.course-unit.status-bar.visibility.ready',
defaultMessage: 'Ready',
description: 'Text for the Ready Badge in the status bar.',
},
statusBarStaffOnly: {
id: 'course-authoring.course-unit.status-bar.visibility.staff-only',
defaultMessage: 'Visible to Staff-Only',
description: 'Text for the Staff Only Badge in the status bar.',
},
statusBarUpcomingBadge: {
id: 'course-authoring.course-unit.status-bar.visibility.Upcoming',
defaultMessage: 'Upcoming',
description: 'Text for the Upcoming Badge in the status bar.',
},
statusBarUnpublishedBadge: {
id: 'course-authoring.course-unit.status-bar.publish-status.unpublished',
defaultMessage: 'Unpublished',
description: 'Text for the Unpublished Badge in the status bar.',
},
statusBarDraftChangesBadge: {
id: 'course-authoring.course-unit.status-bar.publish-status.draft-changes',
defaultMessage: 'Draft Changes',
description: 'Text for the Draft Changes Badge in the status bar.',
},
statusBarPublishedBadge: {
id: 'course-authoring.course-unit.status-bar.publish-status.published',
defaultMessage: 'Published',
description: 'Text for the Published Badge in the status bar.',
},
statusBarDiscussionsEnabled: {
id: 'course-authoring.course-unit.status-bar.discussions-enabled',
defaultMessage: 'Discussions Enabled',
description: 'Text for the Discussions enabled Badge in the status bar.',
},
});

export default messages;
2 changes: 1 addition & 1 deletion src/course-unit/hooks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const useCourseUnit = ({ courseId, blockId }) => {
const dispatch = useDispatch();
const [searchParams] = useSearchParams();
const { sendMessageToIframe } = useIframe();
const [addComponentTemplateData, setAddComponentTemplateData] = useState({});
const [addComponentTemplateData, setAddComponentTemplateData] = useState(undefined);
const [isMoveModalOpen, openMoveModal, closeMoveModal] = useToggle(false);

const courseUnit = useSelector(getCourseUnitData);
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions src/generic/alert-message/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { Alert } from '@openedx/paragon';

interface Props extends React.ComponentPropsWithoutRef<typeof Alert> {
title?: string;
interface Props extends Omit<React.ComponentPropsWithoutRef<typeof Alert>, 'title'> {
title?: string | React.ReactNode;
description?: string | React.ReactNode;
}

Expand Down
Loading