From 0e829974ef0101e85587e8e615908f4b25485e37 Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Wed, 10 Jan 2024 19:47:33 +0530 Subject: [PATCH] feat: add colored left border to items in course outline refactor: move common styles to conditional sortable element --- src/course-outline/CourseOutline.jsx | 109 ++++++---------- src/course-outline/CourseOutline.test.jsx | 31 ++--- .../__mocks__/courseOutlineIndex.js | 4 +- .../ConditionalSortableElement.jsx | 13 +- .../section-card/SectionCard.jsx | 123 ++++++++++-------- .../subsection-card/SubsectionCard.jsx | 92 +++++++------ src/course-outline/unit-card/UnitCard.jsx | 56 +++++--- src/course-outline/unit-card/UnitCard.scss | 6 +- src/course-outline/utils.jsx | 35 +++++ 9 files changed, 260 insertions(+), 209 deletions(-) diff --git a/src/course-outline/CourseOutline.jsx b/src/course-outline/CourseOutline.jsx index b0c9844dd..fe9baf17e 100644 --- a/src/course-outline/CourseOutline.jsx +++ b/src/course-outline/CourseOutline.jsx @@ -42,7 +42,6 @@ import EmptyPlaceholder from './empty-placeholder/EmptyPlaceholder'; import PublishModal from './publish-modal/PublishModal'; import ConfigureModal from './configure-modal/ConfigureModal'; import DeleteModal from './delete-modal/DeleteModal'; -import ConditionalSortableElement from './drag-helper/ConditionalSortableElement'; import { useCourseOutline } from './hooks'; import messages from './messages'; @@ -203,83 +202,55 @@ const CourseOutline = ({ courseId }) => { <> {sections.map((section, index) => ( - - - - {section.childInfo.children.map((subsection) => ( - - ( + + {subsection.childInfo.children.map((unit) => ( + - {subsection.childInfo.children.map((unit) => ( - - ))} - - - ))} - - - + onDuplicateSubmit={handleDuplicateUnitSubmit} + getTitleLink={getUnitUrl} + /> + ))} + + ))} + + ))} {courseActions.childAddable && ( diff --git a/src/course-outline/CourseOutline.test.jsx b/src/course-outline/CourseOutline.test.jsx index 01624b7f7..178cb3fa6 100644 --- a/src/course-outline/CourseOutline.test.jsx +++ b/src/course-outline/CourseOutline.test.jsx @@ -554,21 +554,19 @@ describe('', () => { }) .reply(200, { dummy: 'value' }); - let mockReturnValue = { ...section, published: true }; - if (elementName === 'subsection') { - mockReturnValue = { - ...section, - childInfo: { - children: [ - { - ...section.childInfo.children[0], - published: true, - }, - ...section.childInfo.children.slice(1), - ], - }, - }; - } else if (elementName === 'unit') { + let mockReturnValue = { + ...section, + childInfo: { + children: [ + { + ...section.childInfo.children[0], + published: true, + }, + ...section.childInfo.children.slice(1), + ], + }, + }; + if (elementName === 'unit') { mockReturnValue = { ...section, childInfo: { @@ -612,8 +610,7 @@ describe('', () => { await checkPublishBtn(unit, unitElement, 'unit'); // check subsection await checkPublishBtn(subsection, subsectionElement, 'subsection'); - // check section - await checkPublishBtn(section, sectionElement, 'section'); + // section doesn't display badges }); it('check configure section when configure query is successful', async () => { diff --git a/src/course-outline/__mocks__/courseOutlineIndex.js b/src/course-outline/__mocks__/courseOutlineIndex.js index 8e9f1eb30..0e508c530 100644 --- a/src/course-outline/__mocks__/courseOutlineIndex.js +++ b/src/course-outline/__mocks__/courseOutlineIndex.js @@ -144,7 +144,7 @@ module.exports = { studioUrl: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%40edx_introduction', releasedToStudents: false, releaseDate: 'Jan 01, 1970 at 05:00 UTC', - visibilityState: 'staff_only', + visibilityState: 'needs_attention', hasExplicitStaffLock: false, start: '1970-01-01T05:00:00Z', graded: false, @@ -214,7 +214,7 @@ module.exports = { studioUrl: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_0270f6de40fc', releasedToStudents: false, releaseDate: 'Jan 01, 1970 at 05:00 UTC', - visibilityState: 'staff_only', + visibilityState: 'needs_attention', hasExplicitStaffLock: false, start: '1970-01-01T05:00:00Z', graded: false, diff --git a/src/course-outline/drag-helper/ConditionalSortableElement.jsx b/src/course-outline/drag-helper/ConditionalSortableElement.jsx index 7873a8cc2..10088a466 100644 --- a/src/course-outline/drag-helper/ConditionalSortableElement.jsx +++ b/src/course-outline/drag-helper/ConditionalSortableElement.jsx @@ -9,11 +9,20 @@ const ConditionalSortableElement = ({ children, componentStyle, }) => { + const style = { + background: 'white', + padding: '1rem 1.5rem', + marginBottom: '1.5rem', + borderRadius: '0.35rem', + boxShadow: '0 0 .125rem rgba(0, 0, 0, .15), 0 0 .25rem rgba(0, 0, 0, .15)', + ...componentStyle, + }; + if (draggable) { return (
{children} @@ -24,7 +33,7 @@ const ConditionalSortableElement = ({ return ( {children} diff --git a/src/course-outline/section-card/SectionCard.jsx b/src/course-outline/section-card/SectionCard.jsx index 61f54f9b1..618131682 100644 --- a/src/course-outline/section-card/SectionCard.jsx +++ b/src/course-outline/section-card/SectionCard.jsx @@ -11,8 +11,9 @@ import { setCurrentItem, setCurrentSection } from '../data/slice'; import { RequestStatus } from '../../data/constants'; import CardHeader from '../card-header/CardHeader'; import BaseTitleWithStatusBadge from '../card-header/BaseTitleWithStatusBadge'; +import ConditionalSortableElement from '../drag-helper/ConditionalSortableElement'; import TitleButton from '../card-header/TitleButton'; -import { getItemStatus, scrollToElement } from '../utils'; +import { getItemStatus, getItemStatusBorder, scrollToElement } from '../utils'; import messages from './messages'; const SectionCard = ({ @@ -64,6 +65,9 @@ const SectionCard = ({ hasChanges, }); + // remove border when section is expanded + const borderStyle = getItemStatusBorder(!isExpanded ? sectionStatus : ''); + const handleExpandContent = () => { setIsExpanded((prevState) => !prevState); }; @@ -112,66 +116,75 @@ const SectionCard = ({ ); return ( -
-
- {isHeaderVisible && ( - - )} -
- {explanatoryMessage &&

{explanatoryMessage}

} -
- -
-
- {isExpanded && ( -
- {children} - {actions.childAddable && ( +
+
+ {isHeaderVisible && ( + + )} +
+ {explanatoryMessage &&

{explanatoryMessage}

} +
- )} +
- )} + {isExpanded && ( +
+ {children} + {actions.childAddable && ( + + )} +
+ )} +
-
+ ); }; diff --git a/src/course-outline/subsection-card/SubsectionCard.jsx b/src/course-outline/subsection-card/SubsectionCard.jsx index f6b0b943e..64d195a6a 100644 --- a/src/course-outline/subsection-card/SubsectionCard.jsx +++ b/src/course-outline/subsection-card/SubsectionCard.jsx @@ -9,8 +9,9 @@ import { setCurrentItem, setCurrentSection, setCurrentSubsection } from '../data import { RequestStatus } from '../../data/constants'; import CardHeader from '../card-header/CardHeader'; import BaseTitleWithStatusBadge from '../card-header/BaseTitleWithStatusBadge'; +import ConditionalSortableElement from '../drag-helper/ConditionalSortableElement'; import TitleButton from '../card-header/TitleButton'; -import { getItemStatus, scrollToElement } from '../utils'; +import { getItemStatus, getItemStatusBorder, scrollToElement } from '../utils'; import messages from './messages'; const SubsectionCard = ({ @@ -46,6 +47,7 @@ const SubsectionCard = ({ visibilityState, hasChanges, }); + const borderStyle = getItemStatusBorder(subsectionStatus); const handleExpandContent = () => { setIsExpanded((prevState) => !prevState); @@ -98,44 +100,56 @@ const SubsectionCard = ({ }, [savingStatus]); return ( -
- {isHeaderVisible && ( - - )} - {isExpanded && ( -
- {children} - {actions.childAddable && ( - - )} -
- )} -
+ +
+ {isHeaderVisible && ( + + )} + {isExpanded && ( +
+ {children} + {actions.childAddable && ( + + )} +
+ )} +
+
); }; diff --git a/src/course-outline/unit-card/UnitCard.jsx b/src/course-outline/unit-card/UnitCard.jsx index 0abb1943d..7a341eef0 100644 --- a/src/course-outline/unit-card/UnitCard.jsx +++ b/src/course-outline/unit-card/UnitCard.jsx @@ -7,8 +7,9 @@ import { setCurrentItem, setCurrentSection, setCurrentSubsection } from '../data import { RequestStatus } from '../../data/constants'; import CardHeader from '../card-header/CardHeader'; import BaseTitleWithStatusBadge from '../card-header/BaseTitleWithStatusBadge'; +import ConditionalSortableElement from '../drag-helper/ConditionalSortableElement'; import TitleLink from '../card-header/TitleLink'; -import { getItemStatus, scrollToElement } from '../utils'; +import { getItemStatus, getItemStatusBorder, scrollToElement } from '../utils'; const UnitCard = ({ unit, @@ -41,6 +42,7 @@ const UnitCard = ({ visibilityState, hasChanges, }); + const borderStyle = getItemStatusBorder(unitStatus); const handleClickMenuButton = () => { dispatch(setCurrentItem(unit)); @@ -91,25 +93,39 @@ const UnitCard = ({ } return ( -
- -
+ +
+ +
+
); }; diff --git a/src/course-outline/unit-card/UnitCard.scss b/src/course-outline/unit-card/UnitCard.scss index a1cbda28f..cf30dfcc2 100644 --- a/src/course-outline/unit-card/UnitCard.scss +++ b/src/course-outline/unit-card/UnitCard.scss @@ -1,9 +1,5 @@ .unit-card { - @include pgn-box-shadow(1, "centered"); - - padding: $spacer 2rem; - margin-bottom: 1.5rem; - background: $light-100; + flex-grow: 1; .unit-card__content { margin: $spacer; diff --git a/src/course-outline/utils.jsx b/src/course-outline/utils.jsx index 2dccd59b3..7032212d9 100644 --- a/src/course-outline/utils.jsx +++ b/src/course-outline/utils.jsx @@ -75,6 +75,40 @@ const getItemStatusBadgeContent = (status, messages, intl) => { } }; +/** + * Get section border color + * @param {string} status - value from on getItemStatus util + * @returns { + * borderLeft: string, + * } + */ +const getItemStatusBorder = (status) => { + switch (status) { + case ITEM_BADGE_STATUS.live: + return { + borderLeft: '5px solid #00688D', + }; + case ITEM_BADGE_STATUS.publishedNotLive: + return { + borderLeft: '5px solid #0D7D4D', + }; + case ITEM_BADGE_STATUS.staffOnly: + return { + borderLeft: '5px solid #000000', + }; + case ITEM_BADGE_STATUS.unpublishedChanges: + return { + borderLeft: '5px solid #F0CC00', + }; + case ITEM_BADGE_STATUS.draft: + return { + borderLeft: '5px solid #F0CC00', + }; + default: + return {}; + } +}; + /** * Get formatted highlights form values * @param {Array} currentHighlights - section highlights @@ -150,6 +184,7 @@ const getVideoSharingOptionText = (id, messages, intl) => { export { getItemStatus, getItemStatusBadgeContent, + getItemStatusBorder, getHighlightsFormValues, getVideoSharingOptionText, scrollToElement,