Skip to content

Commit

Permalink
Merge branch 'beta' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
MonkeyDo committed Feb 20, 2023
2 parents b9e9013 + 816f687 commit 7651e84
Show file tree
Hide file tree
Showing 150 changed files with 8,552 additions and 793 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/push-dev-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ jobs:
run: echo ${{ secrets.DOCKER_HUB_PASSWORD }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
continue-on-error: true

- uses: satackey/action-docker-layer-caching@v0.0.11
continue-on-error: true

- name: Build development image
run: |
docker build \
Expand Down
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
],
"env": {"NODE_ENV":"test","SSR":true},
"internalConsoleOptions": "openOnSessionStart",
"preLaunchTask": "build-website"
"preLaunchTask": ""
},
{
"type": "node",
Expand Down
5 changes: 5 additions & 0 deletions config/config.json.ctmpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
"clientSecret": "{{template "KEY" "musicbrainz/client_secret"}}",
"callbackURL": "{{template "KEY" "musicbrainz/callback_url"}}"
},
"critiquebrainz": {
"clientID": "{{template "KEY" "critiquebrainz/client_id"}}",
"clientSecret": "{{template "KEY" "critiquebrainz/client_secret"}}",
"callbackURL": "{{template "KEY" "critiquebrainz/callback_url"}}"
},
"session": {
{{if service "bookbrainz-redis"}}
{{with index (service "bookbrainz-redis") 0}}
Expand Down
5 changes: 5 additions & 0 deletions config/config.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
"clientSecret": null,
"callbackURL": "http://localhost:9099/cb"
},
"critiquebrainz": {
"clientID": null,
"clientSecret": null,
"callbackURL": "http://localhost:9099/external-service/critiquebrainz/callback"
},
"session": {
"maxAge": 2592000000,
"secret": "Something here!",
Expand Down
5 changes: 5 additions & 0 deletions config/config.local.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
"clientSecret": null,
"callbackURL": "http://localhost:9099/cb"
},
"critiquebrainz": {
"clientID": null,
"clientSecret": null,
"callbackURL": "http://localhost:9099/external-service/critiquebrainz/callback"
},
"session": {
"maxAge": 2592000000,
"secret": "Something here!",
Expand Down
17 changes: 17 additions & 0 deletions enzyme.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* eslint-disable node/no-process-env */
/* Taken from: ListenBrainz */
import * as Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';


Enzyme.configure({adapter: new Adapter()});

// In Node > v15 unhandled promise rejections will terminate the process
if (!process.env.LISTENING_TO_UNHANDLED_REJECTION) {
process.on('unhandledRejection', (err) => {
// eslint-disable-next-line no-console
console.log('Unhandled promise rejection:', err);
});
// Avoid memory leak by adding too many listeners
process.env.LISTENING_TO_UNHANDLED_REJECTION = 'true';
}
27 changes: 18 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
"private": true,
"scripts": {
"clean": "./scripts/clean.sh",
"prepublishOnly": "npm run clean",
"postinstall": "npm run prepublishOnly",
"prepare": "npm run clean",
"build-server-js": "babel src --out-dir lib --source-maps --ignore src/api --extensions .js,.jsx,.ts,.tsx",
"build-api-js": "babel src --out-dir lib --ignore 'src/server','src/client' --extensions .js,.jsx,.ts,.tsx",
"build-scss": "./scripts/build-scss.sh",
Expand All @@ -18,25 +17,26 @@
"debug-watch-server": "cross-env DEBUG=bbsite NODE_ENV=development nodemon src/server/app.js --ext js,jsx,ts,tsx --watch src/server --exec 'babel-node --extensions .js,.jsx,.ts,.tsx'",
"lint": "eslint .",
"lint-errors": "eslint --quiet .",
"test": "npm run lint-errors && cross-env NODE_ENV=test mocha",
"test": "npm run lint-errors && cross-env NODE_ENV=test mocha -r jsdom-global/register",
"test-cov": "npx nyc --reporter=text npm run test",
"test-ci": "NODE_ENV=test mocha --reporter json --reporter-option output=test-results.json",
"jsdoc": "npx jsdoc -r src",
"dupreport": "npx jsinspect src/ || true"
},
"engines": {
"node": ">= 16.0.0"
"node": ">= 16.16.0"
},
"browserslist": "> 0.25%, not dead",
"dependencies": {
"@babel/runtime": "^7.17.7",
"@cospired/i18n-iso-languages": "^4.0.0",
"@elastic/elasticsearch": "^5.6.22",
"@fortawesome/fontawesome-svg-core": "^1.2.30",
"@fortawesome/free-brands-svg-icons": "^5.14.0",
"@fortawesome/free-solid-svg-icons": "^5.14.0",
"@fortawesome/free-brands-svg-icons": "^6.1.1",
"@fortawesome/free-solid-svg-icons": "^6.1.1",
"@fortawesome/react-fontawesome": "^0.1.11",
"array-move": "^3.0.1",
"bookbrainz-data": "2.14.1",
"bookbrainz-data": "3.0.0",
"chart.js": "^2.9.4",
"chartjs-adapter-date-fns": "^1.0.0",
"classnames": "^2.3.1",
Expand All @@ -58,6 +58,7 @@
"lodash": "^4.17.21",
"log": "^6.0.0",
"log-node": "^8.0.3",
"mocha-chai-jest-snapshot": "^1.1.4",
"morgan": "^1.10.0",
"nodemailer": "^6.5.0",
"passport": "^0.5.2",
Expand All @@ -72,8 +73,10 @@
"react-redux": "^7.2.6",
"react-select": "^4.3.1",
"react-select-fast-filter-options": "^0.2.3",
"react-simple-star-rating": "^4.0.5",
"react-sortable-hoc": "^2.0.0",
"react-sticky": "^6.0.1",
"react-tooltip": "^4.2.21",
"redis": "^3.1.2",
"redux": "^3.7.2",
"redux-debounce": "^1.0.1",
Expand All @@ -82,7 +85,7 @@
"serve-favicon": "^2.4.3",
"serve-static": "^1.14.1",
"superagent": "^7.1.1",
"swagger-jsdoc": "^4.0.0",
"swagger-jsdoc": "^6.2.5",
"swagger-ui-express": "^4.3.0",
"validator": "^13.7.0"
},
Expand Down Expand Up @@ -116,6 +119,8 @@
"clean-webpack-plugin": "^4.0.0",
"compression-webpack-plugin": "^9.2.0",
"css-loader": "^6.7.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
"eslint": "^7.30.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-import": "^2.22.1",
Expand All @@ -124,18 +129,22 @@
"eslint-webpack-plugin": "^2.4.1",
"faker": "^4.1.0",
"file-loader": "^6.2.0",
"jsdom": "20.0.0",
"jsdom-global": "3.0.2",
"mini-css-extract-plugin": "^2.5.3",
"mocha": "^9.1.3",
"nodemon": "^2.0.2",
"redux-mock-store": "^1.5.4",
"resolve-url-loader": "^5.0.0",
"rewire": "^5.0.0",
"sass": "^1.49.0",
"sass-loader": "^12.4.0",
"sinon": "^14.0.0",
"typescript": "^4.0.5",
"uuid": "^8.3.2",
"webpack": "^5.69.1",
"webpack-bundle-analyzer": "^4.3.0",
"webpack-cli": "^4.3.0",
"webpack-cli": "^4.10.0",
"webpack-dev-middleware": "^5.3.1",
"webpack-hot-middleware": "^2.25.0"
}
Expand Down
21 changes: 21 additions & 0 deletions sql/migrations/2022-07-19/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
BEGIN TRANSACTION;

CREATE TYPE bookbrainz.external_service_oauth_type AS ENUM (
'critiquebrainz'
);

CREATE TABLE bookbrainz.external_service_oauth (
id SERIAL,
editor_id INTEGER NOT NULL,
service bookbrainz.external_service_oauth_type NOT NULL,
access_token TEXT NOT NULL,
refresh_token TEXT,
token_expires TIMESTAMP,
scopes TEXT[]
);

ALTER TABLE bookbrainz.external_service_oauth ADD CONSTRAINT external_service_oauth_editor_id_service UNIQUE (editor_id, service);

ALTER TABLE bookbrainz.external_service_oauth ADD FOREIGN KEY (editor_id) REFERENCES bookbrainz.editor (id);

COMMIT;
18 changes: 18 additions & 0 deletions sql/schemas/bookbrainz.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ CREATE TYPE bookbrainz.entity_type AS ENUM (
'Series'
);

CREATE TYPE bookbrainz.external_service_oauth_type AS ENUM (
'critiquebrainz'
);

CREATE TABLE bookbrainz.editor_type (
id SERIAL PRIMARY KEY,
label VARCHAR(255) NOT NULL CHECK (label <> '')
Expand Down Expand Up @@ -806,6 +810,20 @@ CREATE TABLE bookbrainz.user_collection_collaborator (
ALTER TABLE bookbrainz.user_collection_collaborator ADD FOREIGN KEY (collection_id) REFERENCES bookbrainz.user_collection (id) ON DELETE CASCADE;
ALTER TABLE bookbrainz.user_collection_collaborator ADD FOREIGN KEY (collaborator_id) REFERENCES bookbrainz.editor (id);

CREATE TABLE bookbrainz.external_service_oauth (
id SERIAL,
editor_id INTEGER NOT NULL,
service bookbrainz.external_service_oauth_type NOT NULL,
access_token TEXT NOT NULL,
refresh_token TEXT,
token_expires TIMESTAMP,
scopes TEXT[]
);

ALTER TABLE bookbrainz.external_service_oauth ADD CONSTRAINT external_service_oauth_editor_id_service UNIQUE (editor_id, service);

ALTER TABLE bookbrainz.external_service_oauth ADD FOREIGN KEY (editor_id) REFERENCES bookbrainz.editor (id);

-- Views --

CREATE VIEW bookbrainz.author AS
Expand Down
19 changes: 11 additions & 8 deletions src/client/components/author-credit-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,17 @@ import {map as _map} from 'lodash';


function AuthorCreditDisplay({names}) {
const nameElements = _map(names, (name) => (
<span key={`author-credit-${name.authorCreditID}-${name.position}`}>
<a href={`/author/${name.authorBBID}`}>
{name.name}
</a>
{name.joinPhrase}
</span>
));
const nameElements = _map(names, (name) => {
const authorBBID = name.authorBBID ?? name.author?.id;
return (
<span key={`author-credit-${authorBBID}`}>
<a href={`/author/${authorBBID}`}>
{name.name}
</a>
{name.joinPhrase}
</span>
);
});

return (
<span>
Expand Down
83 changes: 65 additions & 18 deletions src/client/components/pages/entities/author.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,19 @@

import * as bootstrap from 'react-bootstrap';
import * as entityHelper from '../../../helpers/entity';
import React, {createRef, useCallback} from 'react';

import AverageRating from './average-ratings';
import CBReviewModal from './cbReviewModal';
import EntityAnnotation from './annotation';
import EntityFooter from './footer';
import EntityImage from './image';
import EntityLinks from './links';
import EntityRelatedCollections from './related-collections';
import EntityReviews from './cb-review';
import EntityTitle from './title';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import PropTypes from 'prop-types';
import React from 'react';
import {kebabCase as _kebabCase} from 'lodash';
import {faPlus} from '@fortawesome/free-solid-svg-icons';
import {labelsForAuthor} from '../../../helpers/utils';
Expand All @@ -48,6 +51,8 @@ function AuthorAttributes({author}) {
const beginDate = transformISODateForDisplay(extractAttribute(author.beginDate));
const endDate = transformISODateForDisplay(extractAttribute(author.endDate));
const sortNameOfDefaultAlias = getSortNameOfDefaultAlias(author);
const averageRating = author.reviews?.reviews?.average_rating?.rating || 0;
const reviewsCount = author.reviews?.reviews?.average_rating?.count || 0;

const isGroup = type === 'Group';
const {
Expand All @@ -64,6 +69,10 @@ function AuthorAttributes({author}) {
<dl>
<dt>Sort Name</dt>
<dd>{sortNameOfDefaultAlias}</dd>
<AverageRating
averageRatings={averageRating}
reviewsCount={reviewsCount}
/>
</dl>
</Col>
<Col lg={3}>
Expand Down Expand Up @@ -108,9 +117,29 @@ AuthorAttributes.propTypes = {


function AuthorDisplayPage({entity, identifierTypes, user}) {
const [showCBReviewModal, setShowCBReviewModal] = React.useState(false);
const handleModalToggle = useCallback(() => {
setShowCBReviewModal(!showCBReviewModal);
}, [showCBReviewModal]);

const reviewsRef = createRef();

const handleUpdateReviews = useCallback(() => {
reviewsRef.current.handleClick();
}, [reviewsRef]);

const urlPrefix = getEntityUrl(entity);
return (
<div>
<CBReviewModal
entityBBID={entity.bbid}
entityName={entity.defaultAlias.name}
entityType={entity.type}
handleModalToggle={handleModalToggle}
handleUpdateReviews={handleUpdateReviews}
showModal={showCBReviewModal}
userId={user?.id}
/>
<Row className="entity-display-background">
<Col className="entity-display-image-box text-center" lg={2}>
<EntityImage
Expand All @@ -120,27 +149,45 @@ function AuthorDisplayPage({entity, identifierTypes, user}) {
/>
</Col>
<Col lg={10}>
<EntityTitle entity={entity}/>
<AuthorAttributes author={entity}/>
<EntityTitle
entity={entity}
handleModalToggle={handleModalToggle}
/>
<AuthorAttributes
author={entity}
/>
</Col>
</Row>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
<EntityLinks
entity={entity}
identifierTypes={identifierTypes}
urlPrefix={urlPrefix}
/>
<EntityRelatedCollections collections={entity.collections}/>
<Button
className="margin-top-d15"
href={`/work/create?${_kebabCase(entity.type)}=${entity.bbid}`}
variant="success"
>
<FontAwesomeIcon className="margin-right-0-5" icon={faPlus}/>Add Work
</Button>
</React.Fragment>}
<React.Fragment>
<Row>
<Col lg={8}>
<EntityLinks
entity={entity}
identifierTypes={identifierTypes}
urlPrefix={urlPrefix}
/>
<EntityRelatedCollections collections={entity.collections}/>
<Button
className="margin-top-d15"
href={`/work/create?${_kebabCase(entity.type)}=${entity.bbid}`}
variant="success"
>
<FontAwesomeIcon className="margin-right-0-5" icon={faPlus}/>Add Work
</Button>
</Col>
<Col lg={4}>
<EntityReviews
entityBBID={entity.bbid}
entityReviews={entity.reviews}
entityType={entity.type}
handleModalToggle={handleModalToggle}
ref={reviewsRef}
/>
</Col>
</Row>
</React.Fragment>}
<hr className="margin-top-d40"/>
<EntityFooter
bbid={entity.bbid}
Expand Down

0 comments on commit 7651e84

Please sign in to comment.