Skip to content

Commit 8cef0dc

Browse files
committed
Cleanup AddToCollectionList component.
1 parent 9703e10 commit 8cef0dc

File tree

4 files changed

+59
-173
lines changed

4 files changed

+59
-173
lines changed

client/modules/IDE/actions/collections.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { setToastText, showToast } from './toast';
66

77
const TOAST_DISPLAY_TIME_MS = 1500;
88

9-
// eslint-disable-next-line
109
export function getCollections(username) {
1110
return (dispatch) => {
1211
dispatch(startLoader());
@@ -16,8 +15,7 @@ export function getCollections(username) {
1615
} else {
1716
url = '/collections';
1817
}
19-
console.log(url);
20-
apiClient
18+
return apiClient
2119
.get(url)
2220
.then((response) => {
2321
dispatch({
@@ -27,10 +25,9 @@ export function getCollections(username) {
2725
dispatch(stopLoader());
2826
})
2927
.catch((error) => {
30-
const { response } = error;
3128
dispatch({
3229
type: ActionTypes.ERROR,
33-
error: response.data
30+
error: error?.response?.data
3431
});
3532
dispatch(stopLoader());
3633
});
Lines changed: 55 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -1,183 +1,78 @@
11
import PropTypes from 'prop-types';
2-
import React from 'react';
2+
import React, { useEffect, useState } from 'react';
33
import { Helmet } from 'react-helmet';
4-
import { connect } from 'react-redux';
5-
import { bindActionCreators } from 'redux';
6-
import { withTranslation } from 'react-i18next';
7-
8-
import * as ProjectActions from '../actions/project';
9-
import * as ProjectsActions from '../actions/projects';
10-
import * as CollectionsActions from '../actions/collections';
11-
import * as ToastActions from '../actions/toast';
12-
import * as SortingActions from '../actions/sorting';
13-
import getSortedCollections from '../selectors/collections';
4+
import { useTranslation } from 'react-i18next';
5+
import { useDispatch, useSelector } from 'react-redux';
146
import Loader from '../../App/components/loader';
7+
import {
8+
addToCollection,
9+
getCollections,
10+
removeFromCollection
11+
} from '../actions/collections';
12+
import getSortedCollections from '../selectors/collections';
1513
import QuickAddList from './QuickAddList';
1614

17-
const projectInCollection = (project, collection) =>
18-
collection.items.find((item) => item.projectId === project.id) != null;
15+
const AddToCollectionList = ({ projectId }) => {
16+
const { t } = useTranslation();
1917

20-
class CollectionList extends React.Component {
21-
constructor(props) {
22-
super(props);
18+
const dispatch = useDispatch();
2319

24-
if (props.projectId) {
25-
props.getProject(props.projectId);
26-
}
20+
const username = useSelector((state) => state.user.username);
2721

28-
this.props.getCollections(this.props.username);
22+
const collections = useSelector(getSortedCollections);
2923

30-
this.state = {
31-
hasLoadedData: false
32-
};
33-
}
24+
// TODO: improve loading state
25+
const loading = useSelector((state) => state.loading);
26+
const [hasLoadedData, setHasLoadedData] = useState(false);
27+
const showLoader = loading && !hasLoadedData;
3428

35-
componentDidUpdate(prevProps) {
36-
if (prevProps.loading === true && this.props.loading === false) {
37-
// eslint-disable-next-line react/no-did-update-set-state
38-
this.setState({
39-
hasLoadedData: true
40-
});
41-
}
42-
}
29+
useEffect(() => {
30+
dispatch(getCollections(username)).then(() => setHasLoadedData(true));
31+
}, [dispatch, username]);
4332

44-
getTitle() {
45-
if (this.props.username === this.props.user.username) {
46-
return this.props.t('AddToCollectionList.Title');
47-
}
48-
return this.props.t('AddToCollectionList.AnothersTitle', {
49-
anotheruser: this.props.username
50-
});
51-
}
52-
53-
handleCollectionAdd = (collection) => {
54-
this.props.addToCollection(collection.id, this.props.project.id);
33+
const handleCollectionAdd = (collection) => {
34+
dispatch(addToCollection(collection.id, projectId));
5535
};
5636

57-
handleCollectionRemove = (collection) => {
58-
this.props.removeFromCollection(collection.id, this.props.project.id);
37+
const handleCollectionRemove = (collection) => {
38+
dispatch(removeFromCollection(collection.id, projectId));
5939
};
6040

61-
render() {
62-
const { collections, project } = this.props;
63-
const hasCollections = collections.length > 0;
64-
const collectionWithSketchStatus = collections.map((collection) => ({
65-
...collection,
66-
url: `/${collection.owner.username}/collections/${collection.id}`,
67-
isAdded: projectInCollection(project, collection)
68-
}));
69-
70-
let content = null;
71-
72-
if (this.props.loading && !this.state.hasLoadedData) {
73-
content = <Loader />;
74-
} else if (hasCollections) {
75-
content = (
76-
<QuickAddList
77-
items={collectionWithSketchStatus}
78-
onAdd={this.handleCollectionAdd}
79-
onRemove={this.handleCollectionRemove}
80-
t={this.props.t}
81-
/>
82-
);
83-
} else {
84-
content = this.props.t('AddToCollectionList.Empty');
41+
const collectionWithSketchStatus = collections.map((collection) => ({
42+
...collection,
43+
url: `/${collection.owner.username}/collections/${collection.id}`,
44+
isAdded: collection.items.some((item) => item.projectId === projectId)
45+
}));
46+
47+
const getContent = () => {
48+
if (showLoader) {
49+
return <Loader />;
50+
} else if (collections.length === 0) {
51+
return t('AddToCollectionList.Empty');
8552
}
86-
8753
return (
88-
<div className="collection-add-sketch">
89-
<div className="quick-add-wrapper">
90-
<Helmet>
91-
<title>{this.getTitle()}</title>
92-
</Helmet>
93-
94-
{content}
95-
</div>
96-
</div>
54+
<QuickAddList
55+
items={collectionWithSketchStatus}
56+
onAdd={handleCollectionAdd}
57+
onRemove={handleCollectionRemove}
58+
/>
9759
);
98-
}
99-
}
100-
101-
const ProjectShape = PropTypes.shape({
102-
id: PropTypes.string.isRequired,
103-
name: PropTypes.string.isRequired,
104-
createdAt: PropTypes.string.isRequired,
105-
updatedAt: PropTypes.string.isRequired,
106-
user: PropTypes.shape({
107-
username: PropTypes.string.isRequired
108-
}).isRequired
109-
});
110-
111-
const ItemsShape = PropTypes.shape({
112-
createdAt: PropTypes.string.isRequired,
113-
updatedAt: PropTypes.string.isRequired,
114-
project: ProjectShape
115-
});
60+
};
11661

117-
CollectionList.propTypes = {
118-
user: PropTypes.shape({
119-
username: PropTypes.string,
120-
authenticated: PropTypes.bool.isRequired
121-
}).isRequired,
122-
projectId: PropTypes.string.isRequired,
123-
getCollections: PropTypes.func.isRequired,
124-
getProject: PropTypes.func.isRequired,
125-
addToCollection: PropTypes.func.isRequired,
126-
removeFromCollection: PropTypes.func.isRequired,
127-
collections: PropTypes.arrayOf(
128-
PropTypes.shape({
129-
id: PropTypes.string.isRequired,
130-
name: PropTypes.string.isRequired,
131-
description: PropTypes.string,
132-
createdAt: PropTypes.string.isRequired,
133-
updatedAt: PropTypes.string.isRequired,
134-
items: PropTypes.arrayOf(ItemsShape)
135-
})
136-
).isRequired,
137-
username: PropTypes.string,
138-
loading: PropTypes.bool.isRequired,
139-
project: PropTypes.shape({
140-
id: PropTypes.string,
141-
owner: PropTypes.shape({
142-
id: PropTypes.string
143-
})
144-
}),
145-
t: PropTypes.func.isRequired
62+
return (
63+
<div className="collection-add-sketch">
64+
<div className="quick-add-wrapper">
65+
<Helmet>
66+
<title>{t('AddToCollectionList.Title')}</title>
67+
</Helmet>
68+
{getContent()}
69+
</div>
70+
</div>
71+
);
14672
};
14773

148-
CollectionList.defaultProps = {
149-
project: {
150-
id: undefined,
151-
owner: undefined
152-
},
153-
username: undefined
74+
AddToCollectionList.propTypes = {
75+
projectId: PropTypes.string.isRequired
15476
};
15577

156-
function mapStateToProps(state, ownProps) {
157-
return {
158-
user: state.user,
159-
collections: getSortedCollections(state),
160-
sorting: state.sorting,
161-
loading: state.loading,
162-
project: ownProps.project || state.project,
163-
projectId: ownProps && ownProps.params ? ownProps.prams.project_id : null
164-
};
165-
}
166-
167-
function mapDispatchToProps(dispatch) {
168-
return bindActionCreators(
169-
Object.assign(
170-
{},
171-
CollectionsActions,
172-
ProjectsActions,
173-
ProjectActions,
174-
ToastActions,
175-
SortingActions
176-
),
177-
dispatch
178-
);
179-
}
180-
181-
export default withTranslation()(
182-
connect(mapStateToProps, mapDispatchToProps)(CollectionList)
183-
);
78+
export default AddToCollectionList;

client/modules/IDE/components/SketchList.jsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,7 @@ class SketchList extends React.Component {
545545
}
546546
>
547547
<AddToCollectionList
548-
project={this.state.sketchToAddToCollection}
549-
username={this.props.username}
550-
user={this.props.user}
548+
projectId={this.state.sketchToAddToCollection.id}
551549
/>
552550
</Overlay>
553551
)}

client/modules/IDE/pages/IDEView.jsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -396,11 +396,7 @@ class IDEView extends React.Component {
396396
actions={<CollectionSearchbar />}
397397
isFixedHeight
398398
>
399-
<AddToCollectionList
400-
projectId={this.props.params.project_id}
401-
username={this.props.params.username}
402-
user={this.props.user}
403-
/>
399+
<AddToCollectionList projectId={this.props.params.project_id} />
404400
</Overlay>
405401
)}
406402
{this.props.ide.shareModalVisible && (

0 commit comments

Comments
 (0)