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

Notifications Service #696

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6eefc25
add migrations scripts for notifications table
Aug 31, 2021
700e44a
add subcribe and unsubscribe routes for collection and entity
Aug 31, 2021
9308089
fix eslint errors
Aug 31, 2021
bea6f7f
install events npm package
Aug 31, 2021
454847b
Add Notifications Service and add event listeners
Aug 31, 2021
ee6c17c
Fix code style issues with ESLint
lint-action Aug 31, 2021
bc8c9ad
add subscribe/unsubscribe button in the entity pages
Aug 31, 2021
da4a8a6
Fix code style issues with ESLint
lint-action Aug 31, 2021
bcfb0ad
add subscribe/unsubscribe buttons for collection
Sep 1, 2021
8fb59d6
add primary keys for entity_subscription and collection_subscription
Sep 1, 2021
bb7f790
Merge branch 'notification-service' of github.com:bookbrainz/bookbrai…
Sep 1, 2021
daba75e
add GET /editorId/notifications route
Sep 1, 2021
ee041d1
Fix code style issues with ESLint
lint-action Sep 1, 2021
dfb1f54
don't add another notification if similar already exists
Sep 3, 2021
e0132f6
minor changes
Nov 11, 2021
917d5b9
feat(notification): refactor subscribe button
tr1ten Apr 2, 2022
6cc972d
feat(notifications): refactor routes
tr1ten Apr 2, 2022
fd75e84
Merge branch 'master' into notification-service
tr1ten Apr 2, 2022
7c3ba32
feat(notification): update old component usage
tr1ten Apr 2, 2022
baccf88
feat(notifications): added notifications in navbar
tr1ten Apr 3, 2022
7989606
feat(notification):added time ago for notification
tr1ten Apr 4, 2022
44d3e36
feat(notification): minor improvements
tr1ten Apr 5, 2022
f714500
fixing incorrect imports
tr1ten Apr 5, 2022
5b462e3
correctly importing config file
tr1ten Apr 5, 2022
87e4a18
wrap message handler with try-catch
tr1ten May 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"cross-env": "^7.0.3",
"date-fns": "^2.15.0",
"debug": "^4.3.2",
"events": "^3.3.0",
"express": "^4.17.2",
"express-session": "^1.17.1",
"express-slow-down": "^1.3.1",
Expand All @@ -69,6 +70,7 @@
"react-datepicker": "^4.7.0",
"react-dom": "^16.13.1",
"react-hot-loader": "^4.13.0",
"react-infinite-scroller": "^1.2.5",
"react-redux": "^7.2.6",
"react-select": "^1.1.0",
"react-select-fast-filter-options": "^0.2.3",
Expand Down
7 changes: 7 additions & 0 deletions sql/migrations/2021-09-notification-service/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
BEGIN;

DROP TABLE IF EXISTS bookbrainz.notification;
DROP TABLE IF EXISTS bookbrainz.entity_subscription;
DROP TABLE IF EXISTS bookbrainz.collection_subscription;

COMMIT;
36 changes: 36 additions & 0 deletions sql/migrations/2021-09-notification-service/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
BEGIN;

CREATE TABLE IF NOT EXISTS bookbrainz.notification (
id UUID PRIMARY KEY DEFAULT public.uuid_generate_v4(),
subscriber_id INT NOT NULL,
read BOOLEAN NOT NULL DEFAULT FALSE,
notification_text TEXT NOT NULL CHECK (notification_text <> ''),
notification_redirect_link TEXT NOT NULL CHECK (notification_redirect_link <> ''),
timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT timezone('UTC'::TEXT, now())
);
ALTER TABLE bookbrainz.notification ADD FOREIGN KEY (subscriber_id) REFERENCES bookbrainz.editor (id);

CREATE TABLE bookbrainz.entity_subscription (
bbid UUID,
subscriber_id INT,
PRIMARY KEY (
bbid,
subscriber_id
)
);
ALTER TABLE bookbrainz.entity_subscription ADD FOREIGN KEY (bbid) REFERENCES bookbrainz.entity (bbid);
ALTER TABLE bookbrainz.entity_subscription ADD FOREIGN KEY (subscriber_id) REFERENCES bookbrainz.editor (id);


CREATE TABLE bookbrainz.collection_subscription (
collection_id UUID,
subscriber_id INT,
PRIMARY KEY (
collection_id,
subscriber_id
)
);
ALTER TABLE bookbrainz.collection_subscription ADD FOREIGN KEY (collection_id) REFERENCES bookbrainz.user_collection (id);
ALTER TABLE bookbrainz.collection_subscription ADD FOREIGN KEY (subscriber_id) REFERENCES bookbrainz.editor (id);

COMMIT;
3 changes: 3 additions & 0 deletions src/client/components/pages/collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import PagerElement from './parts/pager';
import PropTypes from 'prop-types';
import React from 'react';
import SubscribeButton from './../subscribe-button';
import WorkTable from './entities/work-table';
import _ from 'lodash';
import request from 'superagent';

Expand Down Expand Up @@ -248,6 +250,7 @@ class CollectionPage extends React.Component {
<CollectionAttributes collection={this.props.collection}/>
</Col>
</Row>
<SubscribeButton id={this.props.collection.id} type="collection"/>
<EntityTable {...propsForTable}/>
{messageComponent}
<div className="margin-top-1 text-left">
Expand Down
3 changes: 2 additions & 1 deletion src/client/components/pages/entities/author.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import * as bootstrap from 'react-bootstrap';
import * as entityHelper from '../../../helpers/entity';

import EntityAnnotation from './annotation';
import EntityFooter from './footer';
import EntityImage from './image';
Expand All @@ -28,6 +27,7 @@ import EntityTitle from './title';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import PropTypes from 'prop-types';
import React from 'react';
import SubscribeButton from '../../subscribe-button';
import {kebabCase as _kebabCase} from 'lodash';
import {faPlus} from '@fortawesome/free-solid-svg-icons';
import {labelsForAuthor} from '../../../helpers/utils';
Expand Down Expand Up @@ -124,6 +124,7 @@ function AuthorDisplayPage({entity, identifierTypes, user}) {
<AuthorAttributes author={entity}/>
</Col>
</Row>
<SubscribeButton id={entity.bbid} type="author"/>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
Expand Down
2 changes: 2 additions & 0 deletions src/client/components/pages/entities/edition-group.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import EntityRelatedCollections from './related-collections';
import EntityTitle from './title';
import PropTypes from 'prop-types';
import React from 'react';
import SubscribeButton from '../../subscribe-button';


const {deletedEntityMessage, getTypeAttribute, getEntityUrl, ENTITY_TYPE_ICONS, getSortNameOfDefaultAlias} = entityHelper;
Expand Down Expand Up @@ -80,6 +81,7 @@ function EditionGroupDisplayPage({entity, identifierTypes, user}) {
<EditionGroupAttributes editionGroup={entity}/>
</Col>
</Row>
<SubscribeButton id={entity.bbid} type="editionGroup"/>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
Expand Down
2 changes: 2 additions & 0 deletions src/client/components/pages/entities/edition.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import EntityTitle from './title';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import PropTypes from 'prop-types';
import React from 'react';
import SubscribeButton from '../../subscribe-button';
import WorksTable from './work-table';
import {faExternalLinkAlt} from '@fortawesome/free-solid-svg-icons';

Expand Down Expand Up @@ -145,6 +146,7 @@ function EditionDisplayPage({entity, identifierTypes, user}) {
{editionGroupSection}
</Col>
</Row>
<SubscribeButton id={entity.bbid} type="edition"/>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
Expand Down
2 changes: 2 additions & 0 deletions src/client/components/pages/entities/publisher.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import EntityRelatedCollections from './related-collections';
import EntityTitle from './title';
import PropTypes from 'prop-types';
import React from 'react';
import SubscribeButton from '../../subscribe-button';


const {deletedEntityMessage, extractAttribute, getTypeAttribute, getEntityUrl,
Expand Down Expand Up @@ -98,6 +99,7 @@ function PublisherDisplayPage({entity, identifierTypes, user}) {
<PublisherAttributes publisher={entity}/>
</Col>
</Row>
<SubscribeButton id={entity.bbid} type="publisher"/>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
Expand Down
2 changes: 2 additions & 0 deletions src/client/components/pages/entities/work.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import EntityRelatedCollections from './related-collections';
import EntityTitle from './title';
import PropTypes from 'prop-types';
import React from 'react';
import SubscribeButton from '../../subscribe-button';


const {deletedEntityMessage, getRelationshipSourceByTypeId, getLanguageAttribute, getTypeAttribute, getEntityUrl,
Expand Down Expand Up @@ -93,6 +94,7 @@ function WorkDisplayPage({entity, identifierTypes, user}) {
<WorkAttributes work={entity}/>
</Col>
</Row>
<SubscribeButton id={entity.bbid} type="work"/>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
Expand Down
55 changes: 55 additions & 0 deletions src/client/components/subscribe-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {Button} from 'react-bootstrap';
import React from 'react';
import request from 'superagent';


type SubscribeButtonProps = {
id:string,
type:string,
};
function SubscribeButton({id, type}:SubscribeButtonProps) {
/* eslint-disable react/jsx-no-bind */
const [isSubscribed, setIsSubscribed] = React.useState(false);
React.useEffect(() => {
request.get(`/${type}/${id}/subscribed`).then(response => {
if (response.body.isSubscribed) {
setIsSubscribed(true);
}
});
});
function handleUnsubscribe() {
const submissionUrl = `/${type}/${id}/unsubscribe`;
request.post(submissionUrl)
.then(() => {
setIsSubscribed(false);
});
}
function handleSubscribe() {
const submissionUrl = `/${type}/${id}/subscribe`;
request.post(submissionUrl)
.then(() => {
setIsSubscribed(true);
});
}
if (!isSubscribed) {
return (
<Button
className="margin-top-d15"
variant="success"
onClick={() => handleSubscribe()}
>
Subscribe
</Button>);
}

return (
<Button
className="margin-top-d15"
variant="danger"
onClick={() => handleUnsubscribe()}
>
Unsubscribe
</Button>);
}

export default SubscribeButton;
Loading