|
| 1 | +import moment from 'moment/moment'; |
| 2 | +import { FormattedDate, useIntl } from '@edx/frontend-platform/i18n'; |
| 3 | +import { getConfig } from '@edx/frontend-platform/config'; |
| 4 | +import { |
| 5 | + Button, Hyperlink, Form, Stack, useToggle, |
| 6 | +} from '@openedx/paragon'; |
| 7 | +import { Link } from 'react-router-dom'; |
| 8 | + |
| 9 | +import { ContentTagsDrawerSheet } from '../../content-tags-drawer'; |
| 10 | +import TagCount from '../../generic/tag-count'; |
| 11 | +import { useHelpUrls } from '../../help-urls/hooks'; |
| 12 | +import { useWaffleFlags } from '../../data/apiHooks'; |
| 13 | +import { VIDEO_SHARING_OPTIONS } from '../constants'; |
| 14 | +import { useContentTagsCount } from '../../generic/data/apiHooks'; |
| 15 | +import messages from './messages'; |
| 16 | +import { getVideoSharingOptionText } from '../utils'; |
| 17 | +import { ReactNode } from 'react'; |
| 18 | +import { CourseOutlineStatusBar } from '@src/course-outline/data/types'; |
| 19 | + |
| 20 | +interface StatusBarItemProps { |
| 21 | + title: string, |
| 22 | + children: ReactNode, |
| 23 | +}; |
| 24 | + |
| 25 | +const StatusBarItem = ({ title, children }: StatusBarItemProps) => ( |
| 26 | + <div className="d-flex flex-column justify-content-between"> |
| 27 | + <h5>{title}</h5> |
| 28 | + <div className="d-flex align-items-center"> |
| 29 | + {children} |
| 30 | + </div> |
| 31 | + </div> |
| 32 | +); |
| 33 | + |
| 34 | +interface LegacyStatusBarProps { |
| 35 | + courseId: string, |
| 36 | + isLoading: boolean, |
| 37 | + openEnableHighlightsModal: () => void, |
| 38 | + handleVideoSharingOptionChange: (value: string) => void, |
| 39 | + statusBarData: CourseOutlineStatusBar, |
| 40 | +}; |
| 41 | + |
| 42 | +export const LegacyStatusBar = ({ |
| 43 | + statusBarData, |
| 44 | + isLoading, |
| 45 | + courseId, |
| 46 | + openEnableHighlightsModal, |
| 47 | + handleVideoSharingOptionChange, |
| 48 | +}: LegacyStatusBarProps) => { |
| 49 | + const intl = useIntl(); |
| 50 | + const waffleFlags = useWaffleFlags(courseId); |
| 51 | + |
| 52 | + const { |
| 53 | + courseReleaseDate, |
| 54 | + highlightsEnabledForMessaging, |
| 55 | + checklist, |
| 56 | + isSelfPaced, |
| 57 | + videoSharingEnabled, |
| 58 | + videoSharingOptions, |
| 59 | + } = statusBarData; |
| 60 | + |
| 61 | + const { |
| 62 | + completedCourseLaunchChecks, |
| 63 | + completedCourseBestPracticesChecks, |
| 64 | + totalCourseLaunchChecks, |
| 65 | + totalCourseBestPracticesChecks, |
| 66 | + } = checklist; |
| 67 | + |
| 68 | + const courseReleaseDateObj = moment.utc(courseReleaseDate, 'MMM DD, YYYY [at] HH:mm UTC', true); |
| 69 | + const checkListTitle = `${completedCourseLaunchChecks + completedCourseBestPracticesChecks}/${totalCourseLaunchChecks + totalCourseBestPracticesChecks}`; |
| 70 | + const scheduleDestination = () => new URL(`settings/details/${courseId}#schedule`, getConfig().STUDIO_BASE_URL).href; |
| 71 | + |
| 72 | + const { |
| 73 | + contentHighlights: contentHighlightsUrl, |
| 74 | + socialSharing: socialSharingUrl, |
| 75 | + } = useHelpUrls(['contentHighlights', 'socialSharing']); |
| 76 | + |
| 77 | + const { data: courseTagCount } = useContentTagsCount(courseId); |
| 78 | + |
| 79 | + const [isManageTagsDrawerOpen, openManageTagsDrawer, closeManageTagsDrawer] = useToggle(false); |
| 80 | + |
| 81 | + if (isLoading) { |
| 82 | + return null; |
| 83 | + } |
| 84 | + |
| 85 | + return ( |
| 86 | + <> |
| 87 | + <Stack direction="horizontal" gap={3.5} className="d-flex align-items-stretch outline-status-bar" data-testid="outline-status-bar"> |
| 88 | + <StatusBarItem title={intl.formatMessage(messages.startDateTitle)}> |
| 89 | + <Link |
| 90 | + className="small" |
| 91 | + to={waffleFlags.useNewScheduleDetailsPage ? `/course/${courseId}/settings/details/#schedule` : scheduleDestination()} |
| 92 | + > |
| 93 | + {courseReleaseDateObj.isValid() ? ( |
| 94 | + <FormattedDate |
| 95 | + value={courseReleaseDateObj.toString()} |
| 96 | + year="numeric" |
| 97 | + month="short" |
| 98 | + day="2-digit" |
| 99 | + hour="numeric" |
| 100 | + minute="numeric" |
| 101 | + /> |
| 102 | + ) : courseReleaseDate} |
| 103 | + </Link> |
| 104 | + </StatusBarItem> |
| 105 | + <StatusBarItem title={intl.formatMessage(messages.pacingTypeTitle)}> |
| 106 | + <span className="small"> |
| 107 | + {isSelfPaced |
| 108 | + ? intl.formatMessage(messages.pacingTypeSelfPaced) |
| 109 | + : intl.formatMessage(messages.pacingTypeInstructorPaced)} |
| 110 | + </span> |
| 111 | + </StatusBarItem> |
| 112 | + <StatusBarItem title={intl.formatMessage(messages.checklistTitle)}> |
| 113 | + <Link |
| 114 | + className="small" |
| 115 | + to={`/course/${courseId}/checklists`} |
| 116 | + > |
| 117 | + {checkListTitle} {intl.formatMessage(messages.checklistCompleted)} |
| 118 | + </Link> |
| 119 | + </StatusBarItem> |
| 120 | + <StatusBarItem title={intl.formatMessage(messages.highlightEmailsTitle)}> |
| 121 | + <div className="d-flex align-items-center"> |
| 122 | + {highlightsEnabledForMessaging ? ( |
| 123 | + <span data-testid="highlights-enabled-span" className="small"> |
| 124 | + {intl.formatMessage(messages.highlightEmailsEnabled)} |
| 125 | + </span> |
| 126 | + ) : ( |
| 127 | + <Button data-testid="highlights-enable-button" size="sm" onClick={openEnableHighlightsModal}> |
| 128 | + {intl.formatMessage(messages.highlightEmailsButton)} |
| 129 | + </Button> |
| 130 | + )} |
| 131 | + <Hyperlink |
| 132 | + className="small ml-2" |
| 133 | + destination={contentHighlightsUrl} |
| 134 | + target="_blank" |
| 135 | + showLaunchIcon={false} |
| 136 | + > |
| 137 | + {intl.formatMessage(messages.highlightEmailsLink)} |
| 138 | + </Hyperlink> |
| 139 | + </div> |
| 140 | + </StatusBarItem> |
| 141 | + {getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && ( |
| 142 | + <StatusBarItem title={intl.formatMessage(messages.courseTagsTitle)}> |
| 143 | + <div className="d-flex align-items-center"> |
| 144 | + <TagCount count={courseTagCount || 0} /> |
| 145 | + { /* eslint-disable-next-line jsx-a11y/anchor-is-valid */ } |
| 146 | + <a |
| 147 | + className="small ml-2" |
| 148 | + href="#" |
| 149 | + onClick={openManageTagsDrawer} |
| 150 | + > |
| 151 | + {intl.formatMessage(messages.courseManageTagsLink)} |
| 152 | + </a> |
| 153 | + </div> |
| 154 | + </StatusBarItem> |
| 155 | + )} |
| 156 | + {videoSharingEnabled && ( |
| 157 | + <Form.Group |
| 158 | + size="sm" |
| 159 | + className="d-flex flex-column justify-content-between m-0" |
| 160 | + > |
| 161 | + <Form.Label |
| 162 | + className="h5" |
| 163 | + >{intl.formatMessage(messages.videoSharingTitle)} |
| 164 | + </Form.Label> |
| 165 | + <div className="d-flex align-items-center"> |
| 166 | + <Form.Control |
| 167 | + as="select" |
| 168 | + defaultValue={videoSharingOptions} |
| 169 | + onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleVideoSharingOptionChange(e.target.value)} |
| 170 | + > |
| 171 | + {Object.values(VIDEO_SHARING_OPTIONS).map((option) => ( |
| 172 | + <option |
| 173 | + key={option} |
| 174 | + value={option} |
| 175 | + > |
| 176 | + {getVideoSharingOptionText(option, messages, intl)} |
| 177 | + </option> |
| 178 | + ))} |
| 179 | + </Form.Control> |
| 180 | + <Hyperlink |
| 181 | + className="small" |
| 182 | + destination={socialSharingUrl} |
| 183 | + target="_blank" |
| 184 | + showLaunchIcon={false} |
| 185 | + > |
| 186 | + {intl.formatMessage(messages.videoSharingLink)} |
| 187 | + </Hyperlink> |
| 188 | + </div> |
| 189 | + </Form.Group> |
| 190 | + |
| 191 | + )} |
| 192 | + </Stack> |
| 193 | + <ContentTagsDrawerSheet |
| 194 | + id={courseId} |
| 195 | + onClose={/* istanbul ignore next */ () => closeManageTagsDrawer()} |
| 196 | + showSheet={isManageTagsDrawerOpen} |
| 197 | + /> |
| 198 | + </> |
| 199 | + ); |
| 200 | +}; |
0 commit comments