From c4df727178745b54bbaae3483a8b6a3427e80bbf Mon Sep 17 00:00:00 2001 From: SundasNoreen Date: Mon, 29 May 2023 23:15:15 +0500 Subject: [PATCH] refactor: refactor components --- package-lock.json | 23 +- package.json | 11 +- src/Notifications/NotificationRowItem.jsx | 76 +++--- src/Notifications/NotificationSections.jsx | 51 ++-- src/Notifications/NotificationTabs.jsx | 9 +- src/Notifications/Notifications.jsx | 70 +++--- src/Notifications/data/api.js | 247 ++++++++++---------- src/Notifications/data/hook.js | 10 + src/__snapshots__/Header.test.jsx.snap | 37 --- src/index.scss | 81 +++---- src/learning-header/LearningHeader.test.jsx | 2 +- 11 files changed, 282 insertions(+), 335 deletions(-) create mode 100644 src/Notifications/data/hook.js diff --git a/package-lock.json b/package-lock.json index 6755cc7..496c013 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 95cbd29..3119dd0 100644 --- a/package.json +++ b/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", diff --git a/src/Notifications/NotificationRowItem.jsx b/src/Notifications/NotificationRowItem.jsx index 263ab8e..ef3bcb3 100644 --- a/src/Notifications/NotificationRowItem.jsx +++ b/src/Notifications/NotificationRowItem.jsx @@ -54,47 +54,45 @@ const NotificationRowItem = ({ notification }) => { const iconComponent = getIconByType(notification.type); return ( -
-
- -
-
-
- - {notification?.respondingUser} {' '} - {getContentMessageByType()} - {notification?.targetUser && ( - <> - {notification?.targetUser} - - {(authenticatedUser && authenticatedUser.username) !== notification.author - ? intl.formatMessage(messages.notificationResponseOnOtherPostLabel) - : intl.formatMessage(messages.notificationResponseOnYourPostLabel)} - - - )} - - {' '}{notification?.notificationContent} - - -
- {notification.status === 'unread' &&
} -
-
- - {notification?.courseName} - - {intl.formatMessage(messages.fullStop)} - - - {timeago.format(notification?.time, 'time-locale')} - +
+ +
+
+
+ + {notification?.respondingUser } {' '} + {getContentMessageByType()} + {notification?.targetUser && ( + <> + {notification.targetUser} + + {(authenticatedUser && authenticatedUser.username) !== notification.author + ? intl.formatMessage(messages.notificationResponseOnOtherPostLabel) + : intl.formatMessage(messages.notificationResponseOnYourPostLabel)} + + + )} + + {' '}{notification?.notificationContent} + +
+ + {notification?.courseName} + {intl.formatMessage(messages.fullStop)} + {timeago.format(notification?.time, 'time-locale')} + +
+ {!notification.isRead && ( +
+ +
+ )}
diff --git a/src/Notifications/NotificationSections.jsx b/src/Notifications/NotificationSections.jsx index 0a2103b..1cd3818 100644 --- a/src/Notifications/NotificationSections.jsx +++ b/src/Notifications/NotificationSections.jsx @@ -14,40 +14,47 @@ const NotificationSections = ({ handleLoadMoreNotification, loadMoreCount }) => return ( notifications && ( -
-
- - {TODAY && TODAY.length > 0 && intl.formatMessage(messages.notificationTodayHeading)} - - {totalCount > 0 && ( - - {intl.formatMessage(messages.notificationMarkAsRead)} - +
+
+ {TODAY && TODAY.length > 0 && ( + <> + + { intl.formatMessage(messages.notificationTodayHeading)} + + {totalCount > 0 && ( + + {intl.formatMessage(messages.notificationMarkAsRead)} + + )} + )}
-
{TODAY && TODAY.map( (notification) => , )} -
- - {EARLIER && EARLIER.length > 0 +
+ + {EARLIER && EARLIER.length > 0 && intl.formatMessage(messages.notificationEarlierHeading)} + + {totalCount > 0 && TODAY && TODAY.length === 0 && ( + + {intl.formatMessage(messages.notificationMarkAsRead)} -
+ )} +
{EARLIER && EARLIER.map( (notification) => , )} {loadMoreCount < totalCount && ( - + )} -
) ); diff --git a/src/Notifications/NotificationTabs.jsx b/src/Notifications/NotificationTabs.jsx index 8fd9cea..4a2748a 100644 --- a/src/Notifications/NotificationTabs.jsx +++ b/src/Notifications/NotificationTabs.jsx @@ -32,8 +32,8 @@ const NotificationTabs = () => { {option.key === selectedNotificationType && } @@ -47,15 +47,14 @@ const NotificationTabs = () => { } return ( - activeTab && ( {tabArray} - ) ); }; diff --git a/src/Notifications/Notifications.jsx b/src/Notifications/Notifications.jsx index 76f1072..c7381ab 100644 --- a/src/Notifications/Notifications.jsx +++ b/src/Notifications/Notifications.jsx @@ -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={(

{intl.formatMessage(messages.notificationTitle)} @@ -78,38 +86,26 @@ const Notifications = () => { )} > - <> - {/* {notificationCounts?.Total > 0 && ( - - {notificationCounts?.Total} - - )} */} -
- { handleNotificationTray(!showNotificationTray); }} - src={NotificationsNone} - iconAs={Icon} - variant="light" - iconClassNames="text-primary-500" - className="ml-4 mr-1 my-3" - style={{ width: '36px', height: '36px' }} - /> - - { notificationCounts?.Total > 0 && notificationCounts?.Total} - -
- +
+ { handleNotificationTray(!showNotificationTray); }} + src={NotificationsNone} + iconAs={Icon} + variant="light" + iconClassNames="text-primary-500" + className="ml-4 mr-1 my-3" + style={{ width: '36px', height: '36px' }} + /> + + { notificationCounts?.count > 0 && notificationCounts?.count} + +
); }; diff --git a/src/Notifications/data/api.js b/src/Notifications/data/api.js index 6f078c1..ff3e680 100644 --- a/src/Notifications/data/api.js +++ b/src/Notifications/data/api.js @@ -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); } diff --git a/src/Notifications/data/hook.js b/src/Notifications/data/hook.js new file mode 100644 index 0000000..9136494 --- /dev/null +++ b/src/Notifications/data/hook.js @@ -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; +} diff --git a/src/__snapshots__/Header.test.jsx.snap b/src/__snapshots__/Header.test.jsx.snap index 3768354..f83161b 100644 --- a/src/__snapshots__/Header.test.jsx.snap +++ b/src/__snapshots__/Header.test.jsx.snap @@ -237,43 +237,6 @@ exports[`
renders correctly for authenticated desktop 1`] = ` aria-label="Secondary" className="nav secondary-menu-container align-items-center ml-auto" > -
-
- -
-
{ it('displays user button', () => { render(
); - expect(screen.getByRole('button')).toHaveTextContent(authenticatedUser.username); + expect(screen.getByText(authenticatedUser.username)).toBeInTheDocument(); }); it('displays course data', () => {