Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions client/modules/IDE/actions/collections.js
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -16,8 +15,7 @@ export function getCollections(username) {
} else {
url = '/collections';
}
console.log(url);
apiClient
return apiClient
.get(url)
.then((response) => {
dispatch({
Expand All @@ -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());
});
Expand Down
213 changes: 55 additions & 158 deletions client/modules/IDE/components/AddToCollectionList.jsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
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 { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
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 {
addToCollection,
getCollections,
removeFromCollection
} from '../actions/collections';
import getSortedCollections from '../selectors/collections';
import QuickAddList from './QuickAddList';
import { remSize } from '../../../theme';

const projectInCollection = (project, collection) =>
collection.items.find((item) => item.projectId === project.id) != null;

export const CollectionAddSketchWrapper = styled.div`
width: ${remSize(600)};
max-width: 100%;
Expand All @@ -31,166 +27,67 @@ export const QuickAddWrapper = styled.div`
height: 100%;
`;

class CollectionList extends React.Component {
constructor(props) {
super(props);
const AddToCollectionList = ({ projectId }) => {
const { t } = useTranslation();

if (props.projectId) {
props.getProject(props.projectId);
}
const dispatch = useDispatch();

this.props.getCollections(this.props.username);
const username = useSelector((state) => state.user.username);

this.state = {
hasLoadedData: false
};
}
const collections = useSelector(getSortedCollections);

componentDidUpdate(prevProps) {
if (prevProps.loading === true && this.props.loading === false) {
// eslint-disable-next-line react/no-did-update-set-state
this.setState({
hasLoadedData: true
});
}
}
// TODO: improve loading state
const loading = useSelector((state) => state.loading);
const [hasLoadedData, setHasLoadedData] = useState(false);
const showLoader = loading && !hasLoadedData;

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
});
}
useEffect(() => {
dispatch(getCollections(username)).then(() => setHasLoadedData(true));
}, [dispatch, 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 = <Loader />;
} else if (hasCollections) {
content = (
<QuickAddList
items={collectionWithSketchStatus}
onAdd={this.handleCollectionAdd}
onRemove={this.handleCollectionRemove}
t={this.props.t}
/>
);
} 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 <Loader />;
} else if (collections.length === 0) {
return t('AddToCollectionList.Empty');
}

return (
<CollectionAddSketchWrapper>
<QuickAddWrapper>
<Helmet>
<title>{this.getTitle()}</title>
</Helmet>
{content}
</QuickAddWrapper>
</CollectionAddSketchWrapper>
<QuickAddList
items={collectionWithSketchStatus}
onAdd={handleCollectionAdd}
onRemove={handleCollectionRemove}
/>
);
}
}

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 (
<CollectionAddSketchWrapper>
<QuickAddWrapper>
<Helmet>
<title>{t('AddToCollectionList.Title')}</title>
</Helmet>
{getContent()}
</QuickAddWrapper>
</CollectionAddSketchWrapper>
);
};

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;
4 changes: 1 addition & 3 deletions client/modules/IDE/components/SketchList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,7 @@ class SketchList extends React.Component {
}
>
<AddToCollectionList
project={this.state.sketchToAddToCollection}
username={this.props.username}
user={this.props.user}
projectId={this.state.sketchToAddToCollection.id}
/>
</Overlay>
)}
Expand Down
6 changes: 1 addition & 5 deletions client/modules/IDE/pages/IDEView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,7 @@ class IDEView extends React.Component {
actions={<CollectionSearchbar />}
isFixedHeight
>
<AddToCollectionList
projectId={this.props.params.project_id}
username={this.props.params.username}
user={this.props.user}
/>
<AddToCollectionList projectId={this.props.params.project_id} />
</Overlay>
)}
{this.props.ide.shareModalVisible && (
Expand Down