refactor: refactor components
This commit is contained in:
23
package-lock.json
generated
23
package-lock.json
generated
@@ -9,19 +9,20 @@
|
||||
"version": "1.0.0-semantically-released",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@edx/paragon": "20.34.0",
|
||||
"@edx/paragon": "20.36.0",
|
||||
"@fortawesome/fontawesome-svg-core": "6.3.0",
|
||||
"@fortawesome/free-brands-svg-icons": "6.3.0",
|
||||
"@fortawesome/free-regular-svg-icons": "6.3.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.3.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@reduxjs/toolkit": "1.9.5",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"lodash": "^4.17.21",
|
||||
"classnames": "2.3.2",
|
||||
"lodash": "4.17.21",
|
||||
"react-redux": "7.2.9",
|
||||
"react-responsive": "8.2.0",
|
||||
"react-transition-group": "4.4.5",
|
||||
"timeago.js": "^4.0.2"
|
||||
"timeago.js": "4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@edx/brand": "npm:@edx/brand-openedx@1.2.0",
|
||||
@@ -29,7 +30,7 @@
|
||||
"@edx/frontend-build": "12.8.27",
|
||||
"@edx/frontend-platform": "4.2.0",
|
||||
"@edx/reactifex": "^2.1.1",
|
||||
"@testing-library/dom": "9.2.0",
|
||||
"@testing-library/dom": "9.3.0",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "10.4.9",
|
||||
"enzyme": "3.11.0",
|
||||
@@ -3148,9 +3149,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/paragon": {
|
||||
"version": "20.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-20.34.0.tgz",
|
||||
"integrity": "sha512-elWDy17qAHsORsqhAyp1SFOmnwKqvgHJrOvoZnw03xXUeHMn7m4j5aH3UIAHHYV/xu2au4g0YSnwni/+KDLP2A==",
|
||||
"version": "20.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/paragon/-/paragon-20.36.0.tgz",
|
||||
"integrity": "sha512-0dn4r1HvcrHY66xmLkLTRIBD09TDrNn6vxWu1XZr2SwkGLf56cI8aGkZEySeOVs/VLWtJRMmMJaSbozCpxvLyg==",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||
"@fortawesome/react-fontawesome": "^0.1.18",
|
||||
@@ -6027,9 +6028,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@testing-library/dom": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.2.0.tgz",
|
||||
"integrity": "sha512-xTEnpUKiV/bMyEsE5bT4oYA0x0Z/colMtxzUY8bKyPXBNLn/e0V4ZjBZkEhms0xE4pv9QsPfSRu9AWS4y5wGvA==",
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.0.tgz",
|
||||
"integrity": "sha512-Dffe68pGwI6WlLRYR2I0piIkyole9cSBH5jGQKCGMRpHW5RHCqAUaqc2Kv0tUyd4dU4DLPKhJIjyKOnjv4tuUw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
|
||||
11
package.json
11
package.json
@@ -38,7 +38,7 @@
|
||||
"@edx/frontend-build": "12.8.27",
|
||||
"@edx/frontend-platform": "4.2.0",
|
||||
"@edx/reactifex": "^2.1.1",
|
||||
"@testing-library/dom": "9.2.0",
|
||||
"@testing-library/dom": "9.3.0",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "10.4.9",
|
||||
"enzyme": "3.11.0",
|
||||
@@ -56,19 +56,20 @@
|
||||
"redux-saga": "1.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@edx/paragon": "20.34.0",
|
||||
"@edx/paragon": "20.36.0",
|
||||
"@fortawesome/fontawesome-svg-core": "6.3.0",
|
||||
"@fortawesome/free-brands-svg-icons": "6.3.0",
|
||||
"@fortawesome/free-regular-svg-icons": "6.3.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.3.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@reduxjs/toolkit": "1.9.5",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"lodash": "^4.17.21",
|
||||
"classnames": "2.3.2",
|
||||
"lodash": "4.17.21",
|
||||
"react-redux": "7.2.9",
|
||||
"react-responsive": "8.2.0",
|
||||
"react-transition-group": "4.4.5",
|
||||
"timeago.js": "^4.0.2"
|
||||
"timeago.js": "4.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@edx/frontend-platform": "^4.0.0",
|
||||
|
||||
@@ -54,47 +54,45 @@ const NotificationRowItem = ({ notification }) => {
|
||||
|
||||
const iconComponent = getIconByType(notification.type);
|
||||
return (
|
||||
<div className="d-flex mb-2">
|
||||
<div className="mr-2 py-4 pr-2.5">
|
||||
<Icon
|
||||
src={iconComponent && iconComponent.icon}
|
||||
style={{ height: '23.33px', width: '23.33px' }}
|
||||
className={iconComponent && iconComponent.class}
|
||||
/>
|
||||
</div>
|
||||
<div className="row d-flex w-100 py-0 px-0 py-2.5">
|
||||
<div style={{ display: 'contents' }} className="col-md-12 w-100">
|
||||
<span className="col-md-11 px-0 text-primary-500 mb-2 w-100 notification-item-content overflow-hidden">
|
||||
{notification?.respondingUser} {' '}
|
||||
<span className="text-gray-500">{getContentMessageByType()} </span>
|
||||
{notification?.targetUser && (
|
||||
<>
|
||||
{notification?.targetUser}
|
||||
<span className="text-gray-500">
|
||||
{(authenticatedUser && authenticatedUser.username) !== notification.author
|
||||
? intl.formatMessage(messages.notificationResponseOnOtherPostLabel)
|
||||
: intl.formatMessage(messages.notificationResponseOnYourPostLabel)}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
<a className="text-primary-500" href={notification.URL}>
|
||||
{' '}{notification?.notificationContent}
|
||||
</a>
|
||||
</span>
|
||||
<div className="col-md-1 d-flex flex-column justify-content-end mb-2">
|
||||
{notification.status === 'unread' && <div className="bg-brand-500 rounded unread" />}
|
||||
</div>
|
||||
<div className="w-100 px-0 py-0 d-flex flex-row align-items-center">
|
||||
<span className="text-gray-500 mb-2 w-100 font-size-12">
|
||||
<span className="">{notification?.courseName}</span>
|
||||
<span className="font-size-12 text-light-700 px-1.5">
|
||||
{intl.formatMessage(messages.fullStop)}
|
||||
</span>
|
||||
<span>
|
||||
{timeago.format(notification?.time, 'time-locale')}
|
||||
</span>
|
||||
<div className="d-flex mb-2 align-items-center">
|
||||
<Icon
|
||||
src={iconComponent && iconComponent.icon}
|
||||
style={{ height: '23.33px', width: '23.33px' }}
|
||||
className={iconComponent && `${iconComponent.class} mr-4`}
|
||||
/>
|
||||
<div className="d-flex w-100" style={{ borderRadius: '100%' }}>
|
||||
<div className="d-flex align-items-center w-100">
|
||||
<div className="py-2 w-100">
|
||||
<span className="line-height-24 px-0 text-primary-500 mb-2 w-100 notification-item-content overflow-hidden">
|
||||
{notification?.respondingUser } {' '}
|
||||
<span className="text-gray-500">{getContentMessageByType()} </span>
|
||||
{notification?.targetUser && (
|
||||
<>
|
||||
{notification.targetUser}
|
||||
<span className="text-gray-500">
|
||||
{(authenticatedUser && authenticatedUser.username) !== notification.author
|
||||
? intl.formatMessage(messages.notificationResponseOnOtherPostLabel)
|
||||
: intl.formatMessage(messages.notificationResponseOnYourPostLabel)}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
<a className="text-primary-500" href={notification.URL}>
|
||||
{' '}{notification?.notificationContent}
|
||||
</a>
|
||||
</span>
|
||||
<div className="w-100 px-0 py-0 d-flex flex-row align-items-center">
|
||||
<span className="font-size-12 text-gray-500 line-height-20">
|
||||
<span>{notification?.courseName}</span>
|
||||
<span className="text-light-700 px-1.5">{intl.formatMessage(messages.fullStop)}</span>
|
||||
<span>{timeago.format(notification?.time, 'time-locale')}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{!notification.isRead && (
|
||||
<div className="d-flex py-1.5 px-1.5 ml-2">
|
||||
<span className="bg-brand-500 rounded unread" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,40 +14,47 @@ const NotificationSections = ({ handleLoadMoreNotification, loadMoreCount }) =>
|
||||
|
||||
return (
|
||||
notifications && (
|
||||
<div className="pt-4 py-2.5">
|
||||
<div className="d-flex flex-row align-items-center pb-2">
|
||||
<span className="w-100 px-0 text-gray-500">
|
||||
{TODAY && TODAY.length > 0 && intl.formatMessage(messages.notificationTodayHeading)}
|
||||
</span>
|
||||
{totalCount > 0 && (
|
||||
<span className="w-100 px-0 text-right text-info-500">
|
||||
{intl.formatMessage(messages.notificationMarkAsRead)}
|
||||
</span>
|
||||
<div className="mt-4 px-4">
|
||||
<div className="d-flex flex-row justify-content-between pb-2">
|
||||
{TODAY && TODAY.length > 0 && (
|
||||
<>
|
||||
<span className="text-gray-500">
|
||||
{ intl.formatMessage(messages.notificationTodayHeading)}
|
||||
</span>
|
||||
{totalCount > 0 && (
|
||||
<span className="text-info-500 line-height-24">
|
||||
{intl.formatMessage(messages.notificationMarkAsRead)}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{TODAY && TODAY.map(
|
||||
(notification) => <NotificationRowItem notification={notification} />,
|
||||
)}
|
||||
<div className="d-flex pb-2 notification-section">
|
||||
<span className="w-100 px-0 text-gray-500">
|
||||
{EARLIER && EARLIER.length > 0
|
||||
<div className="d-flex flex-row justify-content-between pb-2">
|
||||
<span className="text-gray-500">
|
||||
{EARLIER && EARLIER.length > 0
|
||||
&& intl.formatMessage(messages.notificationEarlierHeading)}
|
||||
</span>
|
||||
{totalCount > 0 && TODAY && TODAY.length === 0 && (
|
||||
<span className="text-info-500 line-height-24">
|
||||
{intl.formatMessage(messages.notificationMarkAsRead)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{EARLIER && EARLIER.map(
|
||||
(notification) => <NotificationRowItem notification={notification} />,
|
||||
)}
|
||||
{loadMoreCount < totalCount && (
|
||||
<Button
|
||||
variant="primary"
|
||||
className="mb-2 mb-sm-0 w-100 bg-primary-500"
|
||||
onClick={() => handleLoadMoreNotification(loadMoreCount + 10)}
|
||||
>
|
||||
{intl.formatMessage(messages.loadMoreNotifications)}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
className="w-100 bg-primary-500"
|
||||
onClick={() => handleLoadMoreNotification(loadMoreCount + 10)}
|
||||
>
|
||||
{intl.formatMessage(messages.loadMoreNotifications)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
@@ -32,8 +32,8 @@ const NotificationTabs = () => {
|
||||
<Tab
|
||||
eventKey={option.key}
|
||||
title={option.title}
|
||||
notification={notificationUnseenCounts[option.title]}
|
||||
tabClassName="d-flex flex-row align-items-center pt-0 pb-2.5 line-height-24 px-0 mr-4"
|
||||
notification={notificationUnseenCounts.countByAppName[option.key]}
|
||||
tabClassName="pt-0 pb-2.5 px-2.5 d-flex flex-row align-items-center line-height-24"
|
||||
>
|
||||
{option.key === selectedNotificationType
|
||||
&& <NotificationSections handleLoadMoreNotification={handleLoadMoreNotification} loadMoreCount={loadMoreCount} />}
|
||||
@@ -47,15 +47,14 @@ const NotificationTabs = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
activeTab && (
|
||||
<Tabs
|
||||
variant="tabs"
|
||||
defaultActiveKey={activeTab}
|
||||
className="notification-tabs"
|
||||
onSelect={handleActiveTab}
|
||||
className="px-2.5"
|
||||
>
|
||||
{tabArray}
|
||||
</Tabs>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -3,14 +3,16 @@ import React, {
|
||||
} from 'react';
|
||||
import { NotificationsNone, Settings } from '@edx/paragon/icons';
|
||||
import {
|
||||
Badge, Form, Icon, IconButton, OverlayTrigger, Popover,
|
||||
Badge, Icon, IconButton, OverlayTrigger, Popover,
|
||||
} from '@edx/paragon';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import classNames from 'classnames';
|
||||
import NotificationTabs from './NotificationTabs';
|
||||
import { getNotificationTotalUnseenCounts, getNotificationStatus } from './data/selectors';
|
||||
import { fetchNotificationsCountsList } from './data/thunks';
|
||||
import { messages } from './messages';
|
||||
import { useIsOnDesktop, useIsOnXLDesktop } from './data/hook';
|
||||
|
||||
const Notifications = () => {
|
||||
const [showNotificationTray, setShowNotificationTray] = useState(false);
|
||||
@@ -20,6 +22,8 @@ const Notifications = () => {
|
||||
const dispatch = useDispatch();
|
||||
const notificationStatus = useSelector(getNotificationStatus());
|
||||
const notificationCounts = useSelector(getNotificationTotalUnseenCounts());
|
||||
const isOnDesktop = useIsOnDesktop();
|
||||
const isOnXLDesktop = useIsOnXLDesktop();
|
||||
|
||||
useEffect(() => {
|
||||
if (notificationStatus === 'idle') {
|
||||
@@ -57,14 +61,18 @@ const Notifications = () => {
|
||||
overlay={(
|
||||
<Popover
|
||||
id="popover-positioned-bottom"
|
||||
className="notification-tray-container pt-4.5 pb-4 px-4 overflow-auto d-flex flex-column
|
||||
align-items-start position-absolute mt-2"
|
||||
style={{ maxHeight: 'calc(100% - 68px)', minHeight: '1220px', minWidth: '549px' }}
|
||||
className={classNames('notification-tray-container pt-4.5 pb-4.5 overflow-auto rounded-0 border-0', {
|
||||
'w-100': !isOnDesktop,
|
||||
'notificationbar-desktop-width': isOnDesktop && !isOnXLDesktop,
|
||||
'w-25 notificationbar-XL-width': isOnXLDesktop,
|
||||
})}
|
||||
data-testid="notificationbar"
|
||||
>
|
||||
<div ref={popoverRef}>
|
||||
<Popover.Title
|
||||
as="h3"
|
||||
style={{ border: 'none' }}
|
||||
className="d-flex flex-row justify-content-between py-0 px-0 mb-4"
|
||||
className="d-flex flex-row justify-content-between py-0 mb-4 border-0 px-4"
|
||||
>
|
||||
<h2 className="text-primary-500 font-size-18 line-height-24">
|
||||
{intl.formatMessage(messages.notificationTitle)}
|
||||
@@ -78,38 +86,26 @@ const Notifications = () => {
|
||||
</Popover>
|
||||
)}
|
||||
>
|
||||
<>
|
||||
{/* {notificationCounts?.Total > 0 && (
|
||||
<Badge variant="danger position-absolute px-1.5 py-1.5 d-flex flex-row justify-content-center
|
||||
align-items-center zindex-1"
|
||||
>
|
||||
<Form.Label className="count font-size-9 mt-2">{notificationCounts?.Total}</Form.Label>
|
||||
</Badge>
|
||||
)} */}
|
||||
<div className="" ref={buttonRef}>
|
||||
<IconButton
|
||||
isActive={showNotificationTray}
|
||||
alt="notification bell icon"
|
||||
onClick={() => { handleNotificationTray(!showNotificationTray); }}
|
||||
src={NotificationsNone}
|
||||
iconAs={Icon}
|
||||
variant="light"
|
||||
iconClassNames="text-primary-500"
|
||||
className="ml-4 mr-1 my-3"
|
||||
style={{ width: '36px', height: '36px' }}
|
||||
/>
|
||||
<Badge
|
||||
variant="danger"
|
||||
pill
|
||||
className="font-weight-normal px-1"
|
||||
style={{
|
||||
fontSize: '9px', border: '2px solid white', right: '-3px', top: '18px', fontWeight: '600',
|
||||
}}
|
||||
>
|
||||
{ notificationCounts?.Total > 0 && notificationCounts?.Total}
|
||||
</Badge>
|
||||
</div>
|
||||
</>
|
||||
<div ref={buttonRef}>
|
||||
<IconButton
|
||||
isActive={showNotificationTray}
|
||||
alt="notification bell icon"
|
||||
onClick={() => { handleNotificationTray(!showNotificationTray); }}
|
||||
src={NotificationsNone}
|
||||
iconAs={Icon}
|
||||
variant="light"
|
||||
iconClassNames="text-primary-500"
|
||||
className="ml-4 mr-1 my-3"
|
||||
style={{ width: '36px', height: '36px' }}
|
||||
/>
|
||||
<Badge
|
||||
variant="danger"
|
||||
pill
|
||||
className="font-weight-normal px-1 font-size-9 notification-badge"
|
||||
>
|
||||
{ notificationCounts?.count > 0 && notificationCounts?.count}
|
||||
</Badge>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
export const getApiBaseUrl = () => getConfig().LMS_BASE_URL;
|
||||
import { camelCaseObject } from '@edx/frontend-platform';
|
||||
|
||||
const parseNotificationList = (notificationList) => {
|
||||
const currentTime = Date.now();
|
||||
@@ -17,190 +15,185 @@ export async function getNotifications(notificationType, notificationCount) {
|
||||
const notificationData = [
|
||||
{
|
||||
type: 'post',
|
||||
respondingUser: 'SCM_Lead',
|
||||
notificationContent: 'Hello and welcome to SC0x!',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
time: '1684996319038',
|
||||
},
|
||||
{
|
||||
type: 'post',
|
||||
respondingUser: 'SCM_Lead',
|
||||
notificationContent: 'Hello and welcome to SC0x!',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
time: '1684996319038',
|
||||
},
|
||||
{
|
||||
type: 'post',
|
||||
respondingUser: 'SCM_Lead',
|
||||
notificationContent: 'Hello and welcome to SC0x!',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
time: '1684996319038',
|
||||
responding_user: 'SCM_Lead',
|
||||
notification_content: 'Hello and welcome to SC0x!',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1685361282018',
|
||||
},
|
||||
{
|
||||
type: 'help',
|
||||
respondingUser: 'MITx_Learner',
|
||||
notificationContent: 'What grade does a student need to get in order to pass the course and earn a certificate?',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
time: '1684996339844',
|
||||
responding_user: 'MITx_Learner',
|
||||
notification_content: 'What grade does a student need to get in order to pass the course and earn a certificate?',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1685361282018',
|
||||
},
|
||||
{
|
||||
type: 'post',
|
||||
respondingUser: 'SCM_Lead',
|
||||
notificationContent: 'Hello and welcome to SC0x!',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: 'SCM_Lead',
|
||||
notification_content: 'Hello and welcome to SC0x!',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1684253634808',
|
||||
author: '',
|
||||
},
|
||||
{
|
||||
type: 'help',
|
||||
respondingUser: 'MITx_Learner',
|
||||
notificationContent: 'What grade does a student need to get in order to pass the course and earn a certificate?',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: 'MITx_Learner',
|
||||
notification_content: 'What grade does a student need to get in order to pass the course and earn a certificate?',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1684253736371',
|
||||
author: '',
|
||||
},
|
||||
{
|
||||
type: 'respond',
|
||||
respondingUser: 'MITx_Learner',
|
||||
notificationContent: 'Can’t find linear regression in section 3 review',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: 'MITx_Learner',
|
||||
notification_content: 'Can’t find linear regression in section 3 review',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1684253736371',
|
||||
author: '',
|
||||
},
|
||||
{
|
||||
type: 'comment',
|
||||
respondingUser: 'MITx_Learner',
|
||||
notificationContent: 'Can’t find linear regression in section 3 review',
|
||||
targetUser: 'MITx_Expert’s ',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: 'MITx_Learner',
|
||||
notification_content: 'Can’t find linear regression in section 3 review',
|
||||
target_user: 'MITx_Expert’s ',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1684253736371',
|
||||
author: '',
|
||||
},
|
||||
{
|
||||
type: 'question',
|
||||
respondingUser: 'MITx_Learner',
|
||||
notificationContent: 'Examples of quadratic equations in supply chains',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: 'MITx_Learner',
|
||||
notification_content: 'Examples of quadratic equations in supply chains',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1684253736371',
|
||||
author: '',
|
||||
},
|
||||
{
|
||||
type: 'comment',
|
||||
respondingUser: 'MITx_Learner',
|
||||
notificationContent: 'What grade does a student need to get in order to pass the course and earn a certificate?',
|
||||
targetUser: 'MITx_Expert’s ',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: 'MITx_Learner',
|
||||
notification_content: 'What grade does a student need to get in order to pass the course and earn a certificate?',
|
||||
target_user: 'MITx_Expert’s ',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
time: '1684253736371',
|
||||
is_seen: false,
|
||||
author: 'testuser',
|
||||
},
|
||||
{
|
||||
type: 'comment',
|
||||
respondingUser: 'MITx_Learner',
|
||||
notificationContent: 'Convexity of f(x)=1/x , x>1',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: 'MITx_Learner',
|
||||
notification_content: 'Convexity of f(x)=1/x , x>1',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
time: '1684253736371',
|
||||
is_seen: false,
|
||||
author: 'testuser',
|
||||
},
|
||||
{
|
||||
type: 'answer',
|
||||
respondingUser: 'SCM_Lead',
|
||||
notificationContent: 'Quiz in section 3 - Please explain the F-Significance value',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: 'SCM_Lead',
|
||||
notification_content: 'Quiz in section 3 - Please explain the F-Significance value',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
time: '1685096268835',
|
||||
is_seen: false,
|
||||
author: 'testuser',
|
||||
},
|
||||
{
|
||||
type: 'endorsed',
|
||||
respondingUser: '',
|
||||
notificationContent: 'Quiz in section 3 - Please explain the F-Significance value',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
responding_user: '',
|
||||
notification_content: 'Quiz in section 3 - Please explain the F-Significance value',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1685096268835',
|
||||
author: 'testuser',
|
||||
},
|
||||
{
|
||||
type: 'reported',
|
||||
respondingUser: 'MITx Learner’s',
|
||||
notificationContent: '“Here are the exam answers. Question 1 - CSA stands for Compliance Safety Ac...”',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
time: '1685096268835',
|
||||
responding_user: 'MITx Learner’s',
|
||||
notification_content: '“Here are the exam answers. Question 1 - CSA stands for Compliance Safety Ac...”',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1685212056931',
|
||||
author: '',
|
||||
},
|
||||
{
|
||||
type: 'postLiked',
|
||||
respondingUser: 'SCM_Lead',
|
||||
notificationContent: 'Retaking the course',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
time: '1685096268835',
|
||||
responding_user: 'SCM_Lead',
|
||||
notification_content: 'Retaking the course',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1685212056931',
|
||||
author: '',
|
||||
},
|
||||
{
|
||||
type: 'commentLiked',
|
||||
respondingUser: 'MITx_Expert ',
|
||||
notificationContent: 'Final exam answers',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
time: '1685096268835',
|
||||
responding_user: 'MITx_Expert ',
|
||||
notification_content: 'Final exam answers',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1685212056931',
|
||||
author: '',
|
||||
},
|
||||
{
|
||||
type: 'edited',
|
||||
respondingUser: 'MITx_Expert ',
|
||||
notificationContent: 'Question 1',
|
||||
targetUser: '',
|
||||
courseName: 'Supply Chain Analytics',
|
||||
URL: '',
|
||||
status: 'unread',
|
||||
time: '1685096268835',
|
||||
responding_user: 'MITx_Expert ',
|
||||
notification_content: 'Question 1',
|
||||
target_user: '',
|
||||
course_name: 'Supply Chain Analytics',
|
||||
content_url: '',
|
||||
is_read: false,
|
||||
is_seen: false,
|
||||
time: '1685212056931',
|
||||
author: '',
|
||||
},
|
||||
];
|
||||
|
||||
const { today, earlier } = parseNotificationList(notificationData);
|
||||
const { today, earlier } = parseNotificationList(camelCaseObject(notificationData));
|
||||
|
||||
const data = {
|
||||
discussions: {
|
||||
@@ -233,11 +226,13 @@ export async function getNotifications(notificationType, notificationCount) {
|
||||
|
||||
export async function getNotificationCounts() {
|
||||
const data = {
|
||||
Total: 25,
|
||||
Reminders: 10,
|
||||
Discussions: 5,
|
||||
Grades: 4,
|
||||
Authoring: 6,
|
||||
count: 25,
|
||||
count_by_app_name: {
|
||||
reminders: 10,
|
||||
discussions: 5,
|
||||
grades: 4,
|
||||
authoring: 6,
|
||||
},
|
||||
};
|
||||
return data;
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
10
src/Notifications/data/hook.js
Normal file
10
src/Notifications/data/hook.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { breakpoints, useWindowSize } from '@edx/paragon';
|
||||
|
||||
export function useIsOnDesktop() {
|
||||
const windowSize = useWindowSize();
|
||||
return windowSize.width >= breakpoints.medium.minWidth;
|
||||
}
|
||||
export function useIsOnXLDesktop() {
|
||||
const windowSize = useWindowSize();
|
||||
return windowSize.width >= breakpoints.extraLarge.minWidth;
|
||||
}
|
||||
@@ -237,43 +237,6 @@ exports[`<Header /> renders correctly for authenticated desktop 1`] = `
|
||||
aria-label="Secondary"
|
||||
className="nav secondary-menu-container align-items-center ml-auto"
|
||||
>
|
||||
<div
|
||||
className="mx-4 my-3 bell-container"
|
||||
>
|
||||
<div
|
||||
className="bell-icon-container rounded-circle"
|
||||
>
|
||||
<button
|
||||
className="btn-icon btn-icon-primary btn-icon-md d-inline-block align-bottom ml-1 ml-n1 shadow-none bg-transparent text-primary-500"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
className="btn-icon__icon-container"
|
||||
>
|
||||
<span
|
||||
className="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 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6v-5c0-3.07-1.63-5.64-4.5-6.32V2.5h-3v2.18C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="menu null"
|
||||
onKeyDown={[Function]}
|
||||
|
||||
@@ -122,30 +122,9 @@ $white: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.bell-container{
|
||||
.bell-icon-container{
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
&:hover{
|
||||
background: $light-400;
|
||||
}
|
||||
}
|
||||
.badge{
|
||||
border-radius: 54px;
|
||||
border: 2px solid #FFFFFF;
|
||||
width: 23px;
|
||||
height: 16px;
|
||||
margin-left: 18px;
|
||||
.count{
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.font-size-18{
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.font-size-12{
|
||||
font-size: 12px;
|
||||
}
|
||||
@@ -156,46 +135,44 @@ $white: #fff;
|
||||
.line-height-24{
|
||||
line-height: 24px;
|
||||
}
|
||||
.line-height-20{
|
||||
line-height: 20px;
|
||||
}
|
||||
.icon-size-20{
|
||||
width: 20px !important;
|
||||
height: 20px !important;
|
||||
}
|
||||
.notification-badge{
|
||||
position: absolute;
|
||||
margin-top: 18px;
|
||||
margin-left: -21px;
|
||||
border: 2px solid #FFFFFF;
|
||||
}
|
||||
.notification-tray-container{
|
||||
min-width: 549px;
|
||||
min-height:'1253px';
|
||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.15), 0px 2px 8px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0px 0px 4px 4px;
|
||||
|
||||
.dropdown-toggle::after {
|
||||
display: none;
|
||||
}
|
||||
.expandable{
|
||||
position: relative !important;
|
||||
margin-left: 4px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10rem;
|
||||
font-size: 9px;
|
||||
}
|
||||
.dropdown-toggle{
|
||||
font-size: 14px;
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 12px !important;
|
||||
div{
|
||||
min-height: 6px !important;
|
||||
min-width: 6px !important;
|
||||
}
|
||||
}
|
||||
.dropdown-item{
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.notification-content{
|
||||
.notification-tabs{
|
||||
width: 501px;
|
||||
button{
|
||||
font-size: 14px;
|
||||
}
|
||||
.dropdown-toggle{
|
||||
padding-top: 0px !important;
|
||||
padding-left: 12px !important;
|
||||
div{
|
||||
min-height: 6px;
|
||||
min-width: 6px;
|
||||
}
|
||||
}
|
||||
.dropdown-item{
|
||||
font-size:14px;
|
||||
color: $primary-500;
|
||||
font-weight: 500;
|
||||
}
|
||||
.expandable{
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
padding: 6px 7px;
|
||||
position: relative;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
.notification-item-content{
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
|
||||
@@ -12,7 +12,7 @@ describe('Header', () => {
|
||||
|
||||
it('displays user button', () => {
|
||||
render(<Header />);
|
||||
expect(screen.getByRole('button')).toHaveTextContent(authenticatedUser.username);
|
||||
expect(screen.getByText(authenticatedUser.username)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('displays course data', () => {
|
||||
|
||||
Reference in New Issue
Block a user