From 8cef0dc5ee7c4678b664b21dd12af0fc08fcace6 Mon Sep 17 00:00:00 2001 From: Linda Paiste Date: Sat, 5 Aug 2023 17:27:48 -0500 Subject: [PATCH 1/4] Cleanup AddToCollectionList component. --- client/modules/IDE/actions/collections.js | 7 +- .../IDE/components/AddToCollectionList.jsx | 215 +++++------------- client/modules/IDE/components/SketchList.jsx | 4 +- client/modules/IDE/pages/IDEView.jsx | 6 +- 4 files changed, 59 insertions(+), 173 deletions(-) diff --git a/client/modules/IDE/actions/collections.js b/client/modules/IDE/actions/collections.js index 5a9218520b..dbd2cdae48 100644 --- a/client/modules/IDE/actions/collections.js +++ b/client/modules/IDE/actions/collections.js @@ -6,7 +6,6 @@ import { setToastText, showToast } from './toast'; const TOAST_DISPLAY_TIME_MS = 1500; -// eslint-disable-next-line export function getCollections(username) { return (dispatch) => { dispatch(startLoader()); @@ -16,8 +15,7 @@ export function getCollections(username) { } else { url = '/collections'; } - console.log(url); - apiClient + return apiClient .get(url) .then((response) => { dispatch({ @@ -27,10 +25,9 @@ export function getCollections(username) { dispatch(stopLoader()); }) .catch((error) => { - const { response } = error; dispatch({ type: ActionTypes.ERROR, - error: response.data + error: error?.response?.data }); dispatch(stopLoader()); }); diff --git a/client/modules/IDE/components/AddToCollectionList.jsx b/client/modules/IDE/components/AddToCollectionList.jsx index 26addfaa34..c12d52d2f2 100644 --- a/client/modules/IDE/components/AddToCollectionList.jsx +++ b/client/modules/IDE/components/AddToCollectionList.jsx @@ -1,183 +1,78 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import { withTranslation } from 'react-i18next'; - -import * as ProjectActions from '../actions/project'; -import * as ProjectsActions from '../actions/projects'; -import * as CollectionsActions from '../actions/collections'; -import * as ToastActions from '../actions/toast'; -import * as SortingActions from '../actions/sorting'; -import getSortedCollections from '../selectors/collections'; +import { useTranslation } from 'react-i18next'; +import { useDispatch, useSelector } from 'react-redux'; import Loader from '../../App/components/loader'; +import { + addToCollection, + getCollections, + removeFromCollection +} from '../actions/collections'; +import getSortedCollections from '../selectors/collections'; import QuickAddList from './QuickAddList'; -const projectInCollection = (project, collection) => - collection.items.find((item) => item.projectId === project.id) != null; +const AddToCollectionList = ({ projectId }) => { + const { t } = useTranslation(); -class CollectionList extends React.Component { - constructor(props) { - super(props); + const dispatch = useDispatch(); - if (props.projectId) { - props.getProject(props.projectId); - } + const username = useSelector((state) => state.user.username); - this.props.getCollections(this.props.username); + const collections = useSelector(getSortedCollections); - this.state = { - hasLoadedData: false - }; - } + // TODO: improve loading state + const loading = useSelector((state) => state.loading); + const [hasLoadedData, setHasLoadedData] = useState(false); + const showLoader = loading && !hasLoadedData; - componentDidUpdate(prevProps) { - if (prevProps.loading === true && this.props.loading === false) { - // eslint-disable-next-line react/no-did-update-set-state - this.setState({ - hasLoadedData: true - }); - } - } + useEffect(() => { + dispatch(getCollections(username)).then(() => setHasLoadedData(true)); + }, [dispatch, username]); - getTitle() { - if (this.props.username === this.props.user.username) { - return this.props.t('AddToCollectionList.Title'); - } - return this.props.t('AddToCollectionList.AnothersTitle', { - anotheruser: this.props.username - }); - } - - handleCollectionAdd = (collection) => { - this.props.addToCollection(collection.id, this.props.project.id); + const handleCollectionAdd = (collection) => { + dispatch(addToCollection(collection.id, projectId)); }; - handleCollectionRemove = (collection) => { - this.props.removeFromCollection(collection.id, this.props.project.id); + const handleCollectionRemove = (collection) => { + dispatch(removeFromCollection(collection.id, projectId)); }; - render() { - const { collections, project } = this.props; - const hasCollections = collections.length > 0; - const collectionWithSketchStatus = collections.map((collection) => ({ - ...collection, - url: `/${collection.owner.username}/collections/${collection.id}`, - isAdded: projectInCollection(project, collection) - })); - - let content = null; - - if (this.props.loading && !this.state.hasLoadedData) { - content = ; - } else if (hasCollections) { - content = ( - - ); - } else { - content = this.props.t('AddToCollectionList.Empty'); + const collectionWithSketchStatus = collections.map((collection) => ({ + ...collection, + url: `/${collection.owner.username}/collections/${collection.id}`, + isAdded: collection.items.some((item) => item.projectId === projectId) + })); + + const getContent = () => { + if (showLoader) { + return ; + } else if (collections.length === 0) { + return t('AddToCollectionList.Empty'); } - return ( -
-
- - {this.getTitle()} - - - {content} -
-
+ ); - } -} - -const ProjectShape = PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - createdAt: PropTypes.string.isRequired, - updatedAt: PropTypes.string.isRequired, - user: PropTypes.shape({ - username: PropTypes.string.isRequired - }).isRequired -}); - -const ItemsShape = PropTypes.shape({ - createdAt: PropTypes.string.isRequired, - updatedAt: PropTypes.string.isRequired, - project: ProjectShape -}); + }; -CollectionList.propTypes = { - user: PropTypes.shape({ - username: PropTypes.string, - authenticated: PropTypes.bool.isRequired - }).isRequired, - projectId: PropTypes.string.isRequired, - getCollections: PropTypes.func.isRequired, - getProject: PropTypes.func.isRequired, - addToCollection: PropTypes.func.isRequired, - removeFromCollection: PropTypes.func.isRequired, - collections: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - description: PropTypes.string, - createdAt: PropTypes.string.isRequired, - updatedAt: PropTypes.string.isRequired, - items: PropTypes.arrayOf(ItemsShape) - }) - ).isRequired, - username: PropTypes.string, - loading: PropTypes.bool.isRequired, - project: PropTypes.shape({ - id: PropTypes.string, - owner: PropTypes.shape({ - id: PropTypes.string - }) - }), - t: PropTypes.func.isRequired + return ( +
+
+ + {t('AddToCollectionList.Title')} + + {getContent()} +
+
+ ); }; -CollectionList.defaultProps = { - project: { - id: undefined, - owner: undefined - }, - username: undefined +AddToCollectionList.propTypes = { + projectId: PropTypes.string.isRequired }; -function mapStateToProps(state, ownProps) { - return { - user: state.user, - collections: getSortedCollections(state), - sorting: state.sorting, - loading: state.loading, - project: ownProps.project || state.project, - projectId: ownProps && ownProps.params ? ownProps.prams.project_id : null - }; -} - -function mapDispatchToProps(dispatch) { - return bindActionCreators( - Object.assign( - {}, - CollectionsActions, - ProjectsActions, - ProjectActions, - ToastActions, - SortingActions - ), - dispatch - ); -} - -export default withTranslation()( - connect(mapStateToProps, mapDispatchToProps)(CollectionList) -); +export default AddToCollectionList; diff --git a/client/modules/IDE/components/SketchList.jsx b/client/modules/IDE/components/SketchList.jsx index af03453e0d..8060aace1a 100644 --- a/client/modules/IDE/components/SketchList.jsx +++ b/client/modules/IDE/components/SketchList.jsx @@ -545,9 +545,7 @@ class SketchList extends React.Component { } > )} diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index 24ff858d99..66956ede29 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -396,11 +396,7 @@ class IDEView extends React.Component { actions={} isFixedHeight > - + )} {this.props.ide.shareModalVisible && ( From 79e6cbb2e918b3ad8eccaa9b6ac3e2154a5cbfa0 Mon Sep 17 00:00:00 2001 From: raclim Date: Wed, 10 Jan 2024 13:51:53 -0500 Subject: [PATCH 2/4] update prop for AddToCollectionList in IDEOverlays --- client/modules/IDE/components/IDEOverlays.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/modules/IDE/components/IDEOverlays.jsx b/client/modules/IDE/components/IDEOverlays.jsx index 6dba0e76f5..db0476f4ba 100644 --- a/client/modules/IDE/components/IDEOverlays.jsx +++ b/client/modules/IDE/components/IDEOverlays.jsx @@ -79,8 +79,7 @@ export default function IDEOverlays() { isFixedHeight > )} From d5e24a21891f9f13631520d12f5f00f51dca53d2 Mon Sep 17 00:00:00 2001 From: raclim Date: Wed, 10 Jan 2024 14:10:27 -0500 Subject: [PATCH 3/4] remove unused line --- client/modules/IDE/components/IDEOverlays.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/client/modules/IDE/components/IDEOverlays.jsx b/client/modules/IDE/components/IDEOverlays.jsx index db0476f4ba..84737d3cbc 100644 --- a/client/modules/IDE/components/IDEOverlays.jsx +++ b/client/modules/IDE/components/IDEOverlays.jsx @@ -25,7 +25,6 @@ export default function IDEOverlays() { const { t } = useTranslation(); const dispatch = useDispatch(); const location = useLocation(); - const params = useParams(); const { modalIsVisible, From 6cc1177e1c8568c438451abdfa68f31e48bd445e Mon Sep 17 00:00:00 2001 From: raclim Date: Wed, 10 Jan 2024 14:16:07 -0500 Subject: [PATCH 4/4] remove unused import --- client/modules/IDE/components/IDEOverlays.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/IDE/components/IDEOverlays.jsx b/client/modules/IDE/components/IDEOverlays.jsx index 84737d3cbc..92f8256ae8 100644 --- a/client/modules/IDE/components/IDEOverlays.jsx +++ b/client/modules/IDE/components/IDEOverlays.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; -import { useLocation, useParams } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; import Overlay from '../../App/components/Overlay'; import { closeKeyboardShortcutModal,