diff --git a/package.json b/package.json index 33f83fd093..61e302d738 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,12 @@ "@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": "^6.1.1", + "@fortawesome/fontawesome-svg-core": "^6.4.2", + "@fortawesome/free-brands-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/react-fontawesome": "^0.1.11", "array-move": "^3.0.1", - "bookbrainz-data": "4.1.1", + "bookbrainz-data": "^5.0.0", "chart.js": "^2.9.4", "chartjs-adapter-date-fns": "^1.0.0", "classnames": "^2.3.2", @@ -47,7 +47,7 @@ "date-fns": "^2.15.0", "debug": "^4.3.2", "express": "^4.18.2", - "express-session": "^1.17.1", + "express-session": "^1.17.3", "express-slow-down": "^1.3.1", "http-status": "^1.6.2", "immutable": "^3.8.2", @@ -70,7 +70,7 @@ "react-datepicker": "^4.7.0", "react-dom": "^16.13.1", "react-hot-loader": "^4.13.0", - "react-redux": "^7.2.6", + "react-redux": "^8.1.3", "react-select": "^4.3.1", "react-select-fast-filter-options": "^0.2.3", "react-simple-star-rating": "^4.0.5", @@ -94,16 +94,16 @@ "@babel/core": "^7.20.12", "@babel/node": "^7.14.2", "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/plugin-proposal-object-rest-spread": "^7.17.3", + "@babel/plugin-proposal-object-rest-spread": "^7.20.7", "@babel/plugin-transform-classes": "^7.16.7", "@babel/plugin-transform-runtime": "^7.17.0", "@babel/preset-env": "^7.10.1", - "@babel/preset-react": "^7.18.6", + "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.12.1", - "@babel/register": "^7.17.0", - "@faker-js/faker": "^7.2.0", + "@babel/register": "^7.23.7", + "@faker-js/faker": "^8.1.0", "@types/express": "^4.17.15", - "@types/lodash": "^4.14.191", + "@types/lodash": "^4.14.202", "@types/react-select": "^4.0.18", "@typescript-eslint/eslint-plugin": "^4.28.3", "@typescript-eslint/parser": "^4.6.1", @@ -118,7 +118,7 @@ "chai-sorted": "^0.2.0", "clean-webpack-plugin": "^4.0.0", "compression-webpack-plugin": "^9.2.0", - "css-loader": "^6.7.1", + "css-loader": "^6.9.1", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.6", "eslint": "^7.30.0", @@ -127,7 +127,6 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-react": "^7.26.1", "eslint-webpack-plugin": "^2.4.1", - "faker": "^4.1.0", "file-loader": "^6.2.0", "jsdom": "22.1.0", "jsdom-global": "3.0.2", @@ -141,7 +140,6 @@ "sass-loader": "^13.2.0", "sinon": "^14.0.0", "typescript": "^4.0.5", - "uuid": "^8.3.2", "webpack": "^5.76.0", "webpack-bundle-analyzer": "^4.3.0", "webpack-cli": "^4.10.0", diff --git a/src/client/components/input/drag-and-drop.js b/src/client/components/input/drag-and-drop.js deleted file mode 100644 index 4b5e60ec62..0000000000 --- a/src/client/components/input/drag-and-drop.js +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2016 Max Prettyjohns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -import * as bootstrap from 'react-bootstrap'; -import PropTypes from 'prop-types'; -import React from 'react'; - - -const {Card, Form} = bootstrap; - -class DragAndDrop extends React.Component { - constructor() { - super(); - this.handleClick = this.handleClick.bind(this); - this.handleDragOver = this.handleDragOver.bind(this); - this.handleDrop = this.handleDrop.bind(this); - this.state = { - achievement: { - name: 'drag badge to set', - src: '/images/blankbadge.svg' - } - }; - } - - handleClick(ev) { - ev.preventDefault(); - this.setState({ - achievement: { - name: 'drag badge to set', - src: '/images/blankbadge.svg' - } - }); - } - - handleDragOver(ev) { - ev.preventDefault(); - } - - addChild(data) { - this.setState({achievement: data}); - } - - handleDrop(ev) { - ev.preventDefault(); - let data; - - try { - data = JSON.parse(ev.dataTransfer.getData('text')); - } - catch (err) { - return; - } - this.addChild(data); - } - - render() { - return ( - - - - - - -
- {this.state.achievement.name} -
-
-
- ); - } -} - -DragAndDrop.displayName = 'DragAndDrop'; -DragAndDrop.propTypes = { - name: PropTypes.string.isRequired -}; - -export default DragAndDrop; diff --git a/src/client/components/input/drag-and-drop.tsx b/src/client/components/input/drag-and-drop.tsx new file mode 100644 index 0000000000..306bcad22c --- /dev/null +++ b/src/client/components/input/drag-and-drop.tsx @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2016 Max Prettyjohns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +import * as bootstrap from 'react-bootstrap'; +import PropTypes from 'prop-types'; +import React from 'react'; + + +const {Card, Form} = bootstrap; +const {useState, useCallback} = React; + +/** +* The Achievement interface, defining the properties of an achievement. +* @typedef +* @property {string} name - The name of the achievement. +* @property {string} badgeUrl - The source URL of the achievement's badge image. +* @property {number} id - The ID of the achievement. +*/ +type Achievement = { + name: string; + badgeUrl: string | null; + id: number; +}; + +/** + * Props for DragAndDropImage component + * @typedef {Object} Props + * @property {string} name - The name of the DragAndDrop component. + * @property {Achievement} initialAchievement - The initial achievement to display in the card. + */ +type Props = { + name: string; + initialAchievement?: Achievement; +}; + +/** +* A component for a drag-and-drop card that displays an achievement. +* The card displays an image of the achievement and allows the user to drag and drop a different achievement onto it. +* When a new achievement is dropped onto the card, it is displayed instead of the original achievement. +* @param {Props} props - The props object containing the following: +* @returns {JSX.Element} A React component that displays a drag-and-drop card for an achievement. +*/ +function DragAndDrop({name, initialAchievement}: Props): JSX.Element { + const [achievement, setAchievement] = useState(initialAchievement); + const handleClick = useCallback((event: React.MouseEvent) => { + event.preventDefault(); + setAchievement({ + badgeUrl: '/images/blankbadge.svg', + id: null, + name: 'drag badge to set' + }); + }); + const handleDragOver = useCallback((event: React.DragEvent) => { + event.preventDefault(); + }); + const handleDrop = useCallback((event: React.DragEvent) => { + event.preventDefault(); + let data; + + try { + data = JSON.parse(event.dataTransfer.getData('text')); + } + catch (error) { + return; + } + setAchievement({ + badgeUrl: data.src, + id: data.id, + name: data.name + }); + }); + return ( + + + + + + +
+ {achievement.name} +
+
+
+ ); +} + +DragAndDrop.displayName = 'DragAndDrop'; +DragAndDrop.propTypes = { + initialAchievement: PropTypes.shape({ + badgeUrl: PropTypes.string, + id: PropTypes.number, + name: PropTypes.string.isRequired + }), + name: PropTypes.string.isRequired +}; +DragAndDrop.defaultProps = { + initialAchievement: { + badgeUrl: '/images/blankbadge.svg', + id: null, + name: 'drag badge to set' + } +}; + +export default DragAndDrop; diff --git a/src/client/components/pages/entities/cbReviewModal.tsx b/src/client/components/pages/entities/cbReviewModal.tsx index eaafcdca73..73e4154c4f 100644 --- a/src/client/components/pages/entities/cbReviewModal.tsx +++ b/src/client/components/pages/entities/cbReviewModal.tsx @@ -501,8 +501,11 @@ class CBReviewModal extends React.Component< private accessToken = ''; + /* executes getAccessToken() only in a browser to avoid unnecessary server-side calls during component mounting */ componentDidMount = async () => { - this.accessToken = await this.getAccessToken(); + if (typeof window !== "undefined") { + this.accessToken = await this.getAccessToken(); + } }; render() { diff --git a/src/client/components/pages/entities/wikipedia-extract.tsx b/src/client/components/pages/entities/wikipedia-extract.tsx index e8433e425a..95bfb08907 100644 --- a/src/client/components/pages/entities/wikipedia-extract.tsx +++ b/src/client/components/pages/entities/wikipedia-extract.tsx @@ -20,13 +20,13 @@ import {Col, Row} from 'react-bootstrap'; import React, {useEffect, useState} from 'react'; import {WikipediaArticleExtract, buildWikipediaUrl, getWikidataId} from '../../../../common/helpers/wikimedia'; import DOMPurify from 'isomorphic-dompurify'; -import type {EntityT} from 'bookbrainz-data/lib/types/entity'; +import type {LazyLoadedEntityT} from 'bookbrainz-data/lib/types/entity'; import {getAliasLanguageCodes} from '../../../../common/helpers/utils'; import {uniq} from 'lodash'; type Props = { - entity: EntityT, + entity: LazyLoadedEntityT, articleExtract?: WikipediaArticleExtract, }; diff --git a/src/client/components/pages/help.js b/src/client/components/pages/help.js index 3e9d36ce2b..de8e1f3ef7 100644 --- a/src/client/components/pages/help.js +++ b/src/client/components/pages/help.js @@ -128,7 +128,7 @@ function HelpPage() { Example:
  • The Alchemist (philosophical novel) by Paulo Coelho
  • -
  • The Alchemyst (Nicolas Flamel biography) by Michael Scott
  • +
  • The Alchemyst (YA novel featuring Nicolas Flamel) by Michael Scott
diff --git a/src/client/components/pages/parts/editor-achievements.js b/src/client/components/pages/parts/editor-achievements.js index e09b994808..903d0d9399 100644 --- a/src/client/components/pages/parts/editor-achievements.js +++ b/src/client/components/pages/parts/editor-achievements.js @@ -39,6 +39,7 @@ class EditorAchievementTab extends React.Component { */ constructor(props) { super(props); + this.currAchievement = props.currAchievement; this.state = { achievement: props.achievement, editor: props.editor @@ -91,9 +92,18 @@ class EditorAchievementTab extends React.Component { method="post" > - - - + + +