From 7a66be1d54b4dc499ec5236de11010a9ab5c20e7 Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Fri, 5 Mar 2021 12:02:20 +0800 Subject: [PATCH] Add filtering on notifications page - 5193 ## Issue Closes 5193: Add filtering on notifications page ## Approach - Add a combo box, and simply filter out the notifications based on the combo box value. - Selection state is persistent, but reset to All if there are unread ones when entering the page. - Tell the user that "no notifications" could be due to the filter. --- static/app-strings.json | 4 + ui/page/notifications/view.jsx | 147 ++++++++++++++++++++++++--------- 2 files changed, 112 insertions(+), 39 deletions(-) diff --git a/static/app-strings.json b/static/app-strings.json index ff3cb4a0c..9e5e45318 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -1323,6 +1323,10 @@ "Sync YouTube Channel": "Sync YouTube Channel", "Terms": "Terms", "Privacy Policy": "Privacy Policy", + "Comment replies": "Comment replies", + "Daily watch availability": "Daily watch availability", + "Daily watch reminders": "Daily watch reminders", + "New content": "New content", "No notifications": "No notifications", "You don't have any notifications yet, but they will be here when you do!": "You don't have any notifications yet, but they will be here when you do!", "I like this": "I like this", diff --git a/ui/page/notifications/view.jsx b/ui/page/notifications/view.jsx index f8f04836a..727558ba6 100644 --- a/ui/page/notifications/view.jsx +++ b/ui/page/notifications/view.jsx @@ -4,9 +4,13 @@ import React from 'react'; import Page from 'component/page'; import Card from 'component/common/card'; import Spinner from 'component/spinner'; +import { FormField } from 'component/common/form'; import Notification from 'component/notification'; import Button from 'component/button'; +import usePersistedState from 'effects/use-persisted-state'; import Yrbl from 'component/yrbl'; +import * as NOTIFICATIONS from 'constants/notifications'; +import classnames from 'classnames'; type Props = { notifications: Array, @@ -17,9 +21,39 @@ type Props = { doReadNotifications: () => void, }; +const ALL_NOTIFICATIONS = 'all'; + export default function NotificationsPage(props: Props) { const { notifications, fetching, unreadCount, unseenCount, doSeeAllNotifications, doReadNotifications } = props; const hasNotifications = notifications.length > 0; + const [filterBy, setFilterBy] = usePersistedState('notifications--filter-by', 'all'); + const [filteredNotifications, setFilteredNotifications] = React.useState(notifications); + const isFiltered = filterBy !== ALL_NOTIFICATIONS; + + const NOTIFICATION_FILTER_TYPES = [ + ALL_NOTIFICATIONS, + NOTIFICATIONS.NOTIFICATION_CREATOR_SUBSCRIBER, + NOTIFICATIONS.NOTIFICATION_COMMENT, + NOTIFICATIONS.NOTIFICATION_REPLY, + NOTIFICATIONS.DAILY_WATCH_AVAILABLE, + NOTIFICATIONS.DAILY_WATCH_REMIND, + NOTIFICATIONS.NEW_CONTENT, + ]; + + React.useEffect(() => { + if (unseenCount > 0 || unreadCount > 0) { + // If there are unread notifications when entering the page, reset to All. + setFilterBy(ALL_NOTIFICATIONS); + } + }, []); + + React.useEffect(() => { + if (notifications && filterBy !== ALL_NOTIFICATIONS) { + setFilteredNotifications(notifications.filter((n) => n.notification_rule === filterBy)); + } else { + setFilteredNotifications(notifications); + } + }, [notifications, filterBy]); React.useEffect(() => { if (unseenCount > 0) { @@ -36,46 +70,81 @@ export default function NotificationsPage(props: Props) { )} {!fetching && ( <> - {notifications && notifications.length > 0 ? ( - - {__('Notifications')} - {fetching && } - - } - titleActions={ - unreadCount > 0 && ( -