Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Refactor NotificationsPage and NotificationSection #6815

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
Refactor NotificationsPage with useNotifications hook
  • Loading branch information
mcbouslog committed Sep 6, 2023
commit 3bcd7efdb9b0f8f0457c389efb613227d539841e
195 changes: 107 additions & 88 deletions app/pages/notifications/index.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import counterpart from 'counterpart';
import talkClient from 'panoptes-client/lib/talk-client';
import { shape, string } from 'prop-types';
import {
arrayOf,
bool,
func,
oneOfType,
shape,
string
} from 'prop-types';
import React, { useEffect, useState } from 'react';
mcbouslog marked this conversation as resolved.
Show resolved Hide resolved
import { Helmet } from 'react-helmet';
import Translate from 'react-translate-component';

import useNotifications from './useNotifications';
import NotificationSection from './notification-section';
import CollapsableSection from '../../components/collapsable-section';
import Loading from '../../components/loading-indicator';
@@ -19,26 +26,79 @@ counterpart.registerTranslations('en', {
}
});

export function NotificationsSections({
expanded,
groupedNotifications,
handleExpand,
location,
user
}) {
return (
<div>
<div className="list">
{groupedNotifications.map((notification) => {
const opened = notification.section === expanded || groupedNotifications.length === 1;
return (
<CollapsableSection
key={notification.section}
callbackParent={() => {
const section = expanded === notification.section ? false : notification.section;
handleExpand(section);
}}
expanded={opened}
section={notification.section}
>
<NotificationSection
key={notification.id}
location={location}
projectID={notification.project_id}
slug={notification.project_slug}
user={user}
/>
</CollapsableSection>
);
})}
</div>
</div>
);
}

const DEFAULT_HANDLER = () => true;

NotificationsSections.defaultProps = {
expanded: false,
groupedNotifications: [],
handleExpand: DEFAULT_HANDLER
};

NotificationsSections.propTypes = {
expanded: oneOfType([bool, string]),
groupedNotifications: arrayOf(shape({ section: string })),
handleExpand: func
};

export default function NotificationsPage({ location, project, user }) {
const [groupedNotifications, setNotifications] = useState([]);
const [expanded, setExpanded] = useState(false);

useEffect(() => {
if (user) {
getNotifications();
}
}, [user]);
const {
loading,
notifications,
error
} = useNotifications(user);

useEffect(() => {
if (project) {
setExpanded(`project-${project.id}`);
}
}, [project]);

function groupNotifications(notifications) {
function handleExpand(section) {
setExpanded(section);
}

function groupNotifications(allNotifications) {
const projectSections = [];
const projectNotifications = [];
notifications.forEach((notification) => {
allNotifications.forEach((notification) => {
if (projectSections.indexOf(notification.section) < 0) {
if (notification.section === 'zooniverse') {
projectSections.unshift(notification.section);
@@ -49,88 +109,35 @@ export default function NotificationsPage({ location, project, user }) {
}
}
});
if (project && projectSections.indexOf(`project-${project.id}`) < 0) {
talkClient.type('notifications').get({ page: 1, page_size: 1, section: `project-${project.id}` })
.then(([notification]) => {
if (notification) {
projectNotifications.push(notification);
setNotifications(projectNotifications);
setExpanded(`project-${project.id}`);
}
});
}

setNotifications(projectNotifications);
return projectNotifications;
}

function getNotifications() {
talkClient.type('notifications').get({ page: 1, page_size: 50 })
.then((notifications) => {
groupNotifications(notifications);
})
.then(() => {
if (project) setExpanded(`project-${project.id}`);
})
.catch((e) => {
console.error('Unable to load notifications', e);
});
let groupedNotifications = [];
if (notifications?.length > 0) {
groupedNotifications = groupNotifications(notifications);
}

function renderNotifications() {
let notificationView;

if (groupedNotifications.length > 0) {
notificationView = (
<div>
<div className="list">
{groupedNotifications.map((notification) => {
const opened = notification.section === expanded || groupedNotifications.length === 1;
return (
<CollapsableSection
key={notification.section}
callbackParent={() => {
setExpanded(expanded === notification.section ? false : notification.section);
}}
expanded={opened}
section={notification.section}
>
<NotificationSection
key={notification.id}
location={location}
projectID={notification.project_id}
slug={notification.project_slug}
user={user}
/>
</CollapsableSection>
);
})}
</div>
</div>
);
} else if (groupedNotifications.length === 0) {
notificationView = (
<div className="centering talk-module notifications-title">
<Translate content="notifications.noNotifications" />
{' '}
<Translate content="notifications.participation" />
</div>
);
} else {
notificationView = <Loading />;
}

return notificationView;
}

let signedIn;
const headerStyle = project ? 'notifications-title talk-module' : 'notifications-title';

if (user) {
signedIn = renderNotifications();
} else {
signedIn = (
<div className="centering talk-module">
<Translate content="notifications.signedOut" />
let content = '';
if (!user) {
content = (
<Translate content="notifications.signedOut" />
);
} else if (error) {
content = (
<span>{error.message}</span>
);
} else if (loading) {
content = (
<Loading />
);
} else if (notifications?.length === 0) {
content = (
<div className="centering talk-module notifications-title">
<Translate content="notifications.noNotifications" />
{' '}
<Translate content="notifications.participation" />
</div>
);
}
@@ -142,7 +149,19 @@ export default function NotificationsPage({ location, project, user }) {
<h3 className={headerStyle}>
<Translate content="notifications.title" />
</h3>
{signedIn}
{content ? (
<div className="centering talk-module">
{content}
</div>
) : (
<NotificationsSections
expanded={expanded}
groupedNotifications={groupedNotifications}
handleExpand={handleExpand}
location={location}
user={user}
/>
)}
</div>
</div>
);
Loading