diff --git a/client/modules/IDE/components/CollectionList/CollectionList.jsx b/client/modules/IDE/components/CollectionList/CollectionList.jsx
index 9d641f5e66..d29ed5b9bd 100644
--- a/client/modules/IDE/components/CollectionList/CollectionList.jsx
+++ b/client/modules/IDE/components/CollectionList/CollectionList.jsx
@@ -1,313 +1,203 @@
-import PropTypes from 'prop-types';
import React from 'react';
+import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
-import { withTranslation } from 'react-i18next';
-import { connect } from 'react-redux';
-import { bindActionCreators } from 'redux';
+import { useDispatch, useSelector } from 'react-redux';
+import { useState, useEffect } from 'react';
+import { useTranslation } from 'react-i18next';
import classNames from 'classnames';
+import { useParams } from 'react-router-dom';
import { find } from 'lodash';
-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 Loader from '../../../App/components/loader';
import Overlay from '../../../App/components/Overlay';
import AddToCollectionSketchList from '../AddToCollectionSketchList';
import { SketchSearchbar } from '../Searchbar';
-
-import CollectionListRow from './CollectionListRow';
-
import ArrowUpIcon from '../../../../images/sort-arrow-up.svg';
import ArrowDownIcon from '../../../../images/sort-arrow-down.svg';
+import { getProject } from '../../actions/project';
+import { getCollections } from '../../actions/collections';
+import getSortedCollections from '../../selectors/collections';
+import { DIRECTION, toggleDirectionForField } from '../../actions/sorting';
+import CollectionListRow from './CollectionListRow';
-class CollectionList extends React.Component {
- constructor(props) {
- super(props);
-
- if (props.projectId) {
- props.getProject(props.projectId);
- }
-
- this.props.getCollections(this.props.username);
- this.props.resetSorting();
-
- this.state = {
- hasLoadedData: false,
- addingSketchesToCollectionId: null
- };
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.loading === true && this.props.loading === false) {
- // eslint-disable-next-line react/no-did-update-set-state
- this.setState({
- hasLoadedData: true
- });
+const CollectionList = (props) => {
+ const dispatch = useDispatch();
+ const { t } = useTranslation();
+ const { project_id: projectId } = useParams() || { project_id: null };
+ const [hasLoadedData, setHasLoadedData] = useState(false);
+
+ const user = useSelector((state) => state.user);
+ const sorting = useSelector((state) => state.sorting);
+ const loading = useSelector((state) => state.loading);
+ const collections = useSelector((state) => getSortedCollections(state));
+
+ const [
+ addingSketchesToCollectionId,
+ setAddingSketchesToCollectionId
+ ] = useState(null);
+
+ useEffect(() => {
+ if (projectId) {
+ dispatch(getProject(props.username));
}
- }
+ dispatch(getCollections(props.username)).then(() => setHasLoadedData(true));
+ }, [dispatch, props.username]);
- getTitle() {
- if (this.props.username === this.props.user.username) {
- return this.props.t('CollectionList.Title');
+ const getTitle = () => {
+ if (props.username === user.username) {
+ return t('CollectionList.Title');
}
- return this.props.t('CollectionList.AnothersTitle', {
- anotheruser: this.props.username
- });
- }
+ return t('CollectionList.AnothersTitle', { anotheruser: props.username });
+ };
- showAddSketches = (collectionId) => {
- this.setState({
- addingSketchesToCollectionId: collectionId
- });
+ const showAddSketches = (collectionId) => {
+ setAddingSketchesToCollectionId(collectionId);
};
- hideAddSketches = () => {
- this.setState({
- addingSketchesToCollectionId: null
- });
+ const hideAddSketches = () => {
+ setAddingSketchesToCollectionId(null);
};
- hasCollections() {
- return (
- (!this.props.loading || this.state.hasLoadedData) &&
- this.props.collections.length > 0
- );
- }
+ const hasCollections = () =>
+ !loading && hasLoadedData && collections.length > 0;
- _renderLoader() {
- if (this.props.loading && !this.state.hasLoadedData) return ;
- return null;
- }
+ const renderLoader = () => (loading && !hasLoadedData ? : null);
- _renderEmptyTable() {
- if (!this.props.loading && this.props.collections.length === 0) {
+ const renderEmptyTable = () => {
+ if (!loading && collections.length === 0) {
return (
+ // eslint-disable-next-line react/react-in-jsx-scope
- {this.props.t('CollectionList.NoCollections')}
+ {t('CollectionList.NoCollections')}
);
}
return null;
- }
-
- _getButtonLabel = (fieldName, displayName) => {
- const { field, direction } = this.props.sorting;
+ };
+ const getButtonLabel = (fieldName, displayName) => {
+ const { field, direction } = sorting;
let buttonLabel;
if (field !== fieldName) {
- if (field === 'name') {
- buttonLabel = this.props.t('CollectionList.ButtonLabelAscendingARIA', {
- displayName
- });
- } else {
- buttonLabel = this.props.t('CollectionList.ButtonLabelDescendingARIA', {
- displayName
- });
- }
- } else if (direction === SortingActions.DIRECTION.ASC) {
- buttonLabel = this.props.t('CollectionList.ButtonLabelDescendingARIA', {
+ buttonLabel =
+ field === 'name'
+ ? t('CollectionList.ButtonLabelAscendingARIA', { displayName })
+ : t('CollectionList.ButtonLabelDescendingARIA', { displayName });
+ } else if (direction === DIRECTION.ASC) {
+ buttonLabel = t('CollectionList.ButtonLabelDescendingARIA', {
displayName
});
} else {
- buttonLabel = this.props.t('CollectionList.ButtonLabelAscendingARIA', {
+ buttonLabel = t('CollectionList.ButtonLabelAscendingARIA', {
displayName
});
}
return buttonLabel;
};
-
- _renderFieldHeader = (fieldName, displayName) => {
- const { field, direction } = this.props.sorting;
+ const renderFieldHeader = (fieldName, displayName) => {
+ const { field, direction } = sorting;
const headerClass = classNames({
'sketches-table__header': true,
'sketches-table__header--selected': field === fieldName
});
- const buttonLabel = this._getButtonLabel(fieldName, displayName);
+ const buttonLabel = getButtonLabel(fieldName, displayName);
return (
|
);
};
- render() {
- const username =
- this.props.username !== undefined
- ? this.props.username
- : this.props.user.username;
- const { mobile } = this.props;
-
- return (
-
-
- {this.getTitle()}
-
-
- {this._renderLoader()}
- {this._renderEmptyTable()}
- {this.hasCollections() && (
-
-
-
- {this._renderFieldHeader(
- 'name',
- this.props.t('CollectionList.HeaderName')
- )}
- {this._renderFieldHeader(
- 'createdAt',
- this.props.t('CollectionList.HeaderCreatedAt', {
- context: mobile ? 'mobile' : ''
- })
- )}
- {this._renderFieldHeader(
- 'updatedAt',
- this.props.t('CollectionList.HeaderUpdatedAt', {
- context: mobile ? 'mobile' : ''
- })
- )}
- {this._renderFieldHeader(
- 'numItems',
- this.props.t('CollectionList.HeaderNumItems', {
- context: mobile ? 'mobile' : ''
- })
- )}
- |
-
-
-
- {this.props.collections.map((collection) => (
- this.showAddSketches(collection.id)}
- />
- ))}
-
-
- )}
- {this.state.addingSketchesToCollectionId && (
- }
- closeOverlay={this.hideAddSketches}
- isFixedHeight
- >
-
-
- )}
-
- );
- }
-}
-
-CollectionList.propTypes = {
- user: PropTypes.shape({
- username: PropTypes.string,
- authenticated: PropTypes.bool.isRequired
- }).isRequired,
- projectId: PropTypes.string,
- getCollections: PropTypes.func.isRequired,
- getProject: 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
- })
- ).isRequired,
- username: PropTypes.string,
- loading: PropTypes.bool.isRequired,
- toggleDirectionForField: PropTypes.func.isRequired,
- resetSorting: PropTypes.func.isRequired,
- sorting: PropTypes.shape({
- field: PropTypes.string.isRequired,
- direction: PropTypes.string.isRequired
- }).isRequired,
- project: PropTypes.shape({
- id: PropTypes.string,
- owner: PropTypes.shape({
- id: PropTypes.string
- })
- }),
- t: PropTypes.func.isRequired,
- mobile: PropTypes.bool
+ return (
+
+
+ {getTitle()}
+
+
+ {renderLoader()}
+ {renderEmptyTable()}
+ {hasCollections() && (
+
+
+
+ {renderFieldHeader('name', t('CollectionList.HeaderName'))}
+ {renderFieldHeader(
+ 'createdAt',
+ t('CollectionList.HeaderCreatedAt', {
+ context: props.mobile ? 'mobile' : ''
+ })
+ )}
+ {renderFieldHeader(
+ 'updatedAt',
+ t('CollectionList.HeaderUpdatedAt', {
+ context: props.mobile ? 'mobile' : ''
+ })
+ )}
+ {renderFieldHeader(
+ 'numItems',
+ t('CollectionList.HeaderNumItems', {
+ context: props.mobile ? 'mobile' : ''
+ })
+ )}
+ |
+
+
+
+ {collections.map((collection) => (
+ showAddSketches(collection.id)}
+ />
+ ))}
+
+
+ )}
+ {addingSketchesToCollectionId && (
+ }
+ closeOverlay={hideAddSketches}
+ isFixedHeight
+ >
+
+
+ )}
+
+ );
};
-
-CollectionList.defaultProps = {
- projectId: undefined,
- project: {
- id: undefined,
- owner: undefined
- },
- username: undefined,
- mobile: false
+CollectionList.propTypes = {
+ username: PropTypes.string.isRequired,
+ mobile: PropTypes.bool.isRequired
};
-function mapStateToProps(state, ownProps) {
- return {
- user: state.user,
- collections: getSortedCollections(state),
- sorting: state.sorting,
- loading: state.loading,
- project: state.project,
- projectId: ownProps && ownProps.params ? ownProps.params.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 CollectionList;
diff --git a/client/modules/IDE/components/CollectionList/CollectionListRow.jsx b/client/modules/IDE/components/CollectionList/CollectionListRow.jsx
index dafbe21517..3281060415 100644
--- a/client/modules/IDE/components/CollectionList/CollectionListRow.jsx
+++ b/client/modules/IDE/components/CollectionList/CollectionListRow.jsx
@@ -1,21 +1,19 @@
import PropTypes from 'prop-types';
import React, { useState, useRef } from 'react';
-import { connect } from 'react-redux';
+import { useDispatch } from 'react-redux';
+import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
-import { bindActionCreators } from 'redux';
-import { withTranslation } from 'react-i18next';
import MenuItem from '../../../../components/Dropdown/MenuItem';
import TableDropdown from '../../../../components/Dropdown/TableDropdown';
-import * as ProjectActions from '../../actions/project';
-import * as CollectionsActions from '../../actions/collections';
-import * as IdeActions from '../../actions/ide';
-import * as ToastActions from '../../actions/toast';
import dates from '../../../../utils/formatDate';
+import { deleteCollection, editCollection } from '../../actions/collections';
const formatDateCell = (date, mobile = false) =>
dates.format(date, { showTime: !mobile });
-const CollectionListRowBase = (props) => {
+const CollectionListRow = (props) => {
+ const { t } = useTranslation();
+ const dispatch = useDispatch();
const [renameOpen, setRenameOpen] = useState(false);
const [renameValue, setRenameValue] = useState('');
const renameInput = useRef(null);
@@ -27,9 +25,11 @@ const CollectionListRowBase = (props) => {
const updateName = () => {
const isValid = renameValue.trim().length !== 0;
if (isValid) {
- props.editCollection(props.collection.id, {
- name: renameValue.trim()
- });
+ dispatch(
+ editCollection(props.collection.id, {
+ name: renameValue.trim()
+ })
+ );
}
};
@@ -42,12 +42,12 @@ const CollectionListRowBase = (props) => {
closeAll();
if (
window.confirm(
- props.t('Common.DeleteConfirmation', {
+ t('Common.DeleteConfirmation', {
name: props.collection.name
})
)
) {
- props.deleteCollection(props.collection.id);
+ dispatch(deleteCollection(props.collection.id));
}
};
@@ -81,16 +81,16 @@ const CollectionListRowBase = (props) => {
return (
);
@@ -141,7 +141,7 @@ const CollectionListRowBase = (props) => {
);
};
-CollectionListRowBase.propTypes = {
+CollectionListRow.propTypes = {
collection: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
@@ -163,30 +163,12 @@ CollectionListRowBase.propTypes = {
username: PropTypes.string,
authenticated: PropTypes.bool.isRequired
}).isRequired,
- deleteCollection: PropTypes.func.isRequired,
- editCollection: PropTypes.func.isRequired,
onAddSketches: PropTypes.func.isRequired,
- mobile: PropTypes.bool,
- t: PropTypes.func.isRequired
+ mobile: PropTypes.bool
};
-CollectionListRowBase.defaultProps = {
+CollectionListRow.defaultProps = {
mobile: false
};
-function mapDispatchToPropsSketchListRow(dispatch) {
- return bindActionCreators(
- Object.assign(
- {},
- CollectionsActions,
- ProjectActions,
- IdeActions,
- ToastActions
- ),
- dispatch
- );
-}
-
-export default withTranslation()(
- connect(null, mapDispatchToPropsSketchListRow)(CollectionListRowBase)
-);
+export default CollectionListRow;