diff --git a/client/modules/IDE/actions/collections.js b/client/modules/IDE/actions/collections.js index 68a42f500d..e7acd513b1 100644 --- a/client/modules/IDE/actions/collections.js +++ b/client/modules/IDE/actions/collections.js @@ -65,6 +65,32 @@ export function createCollection(collection) { }; } +export function createCollectionAndRefresh(collection, username) { + return (dispatch) => { + dispatch(startLoader()); + const url = '/collections'; + return apiClient + .post(url, collection) + .then((response) => { + dispatch({ type: ActionTypes.CREATE_COLLECTION }); + dispatch(stopLoader()); + + const newCollection = response.data; + dispatch(setToastText(`Created "${newCollection.name}"`)); + dispatch(showToast(TOAST_DISPLAY_TIME_MS)); + + return dispatch(getCollections(username)); + }) + .catch((error) => { + dispatch({ + type: ActionTypes.ERROR, + error: error?.response?.data + }); + dispatch(stopLoader()); + }); + }; +} + export function addToCollection(collectionId, projectId) { return (dispatch) => { dispatch(startLoader()); diff --git a/client/modules/IDE/components/AddToCollectionList.jsx b/client/modules/IDE/components/AddToCollectionList.jsx index 75713367ee..86d7de0ad4 100644 --- a/client/modules/IDE/components/AddToCollectionList.jsx +++ b/client/modules/IDE/components/AddToCollectionList.jsx @@ -1,18 +1,21 @@ import PropTypes from 'prop-types'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { Helmet } from 'react-helmet'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; import styled from 'styled-components'; import { Loader } from '../../App/components/Loader'; +import { Button } from '../../../common/Button'; +import { generateCollectionName } from '../../../utils/generateRandomName'; import { addToCollection, + createCollectionAndRefresh, getCollections, removeFromCollection } from '../actions/collections'; import getSortedCollections from '../selectors/collections'; import QuickAddList from './QuickAddList'; -import { remSize } from '../../../theme'; +import { remSize, prop } from '../../../theme'; export const CollectionAddSketchWrapper = styled.div` width: ${remSize(600)}; @@ -27,6 +30,29 @@ export const QuickAddWrapper = styled.div` height: 100%; `; +const EmptyText = styled.p` + text-align: center; + color: ${prop('primaryTextColor')}; + margin-bottom: ${remSize(16)}; +`; + +const CreateFormWrapper = styled.form` + display: flex; + align-items: center; + gap: ${remSize(8)}; + margin-top: ${remSize(12)}; +`; + +const CreateInput = styled.input` + flex: 1; + padding: ${remSize(8)}; + border: 1px solid ${prop('Button.primary.default.border')}; + border-radius: 2px; + background-color: ${prop('inputSecondaryBackground')}; + color: ${prop('primaryTextColor')}; + font-size: ${remSize(14)}; +`; + const AddToCollectionList = ({ projectId }) => { const { t } = useTranslation(); @@ -41,6 +67,10 @@ const AddToCollectionList = ({ projectId }) => { const [hasLoadedData, setHasLoadedData] = useState(false); const showLoader = loading && !hasLoadedData; + const [showCreateForm, setShowCreateForm] = useState(false); + const generatedName = useMemo(() => generateCollectionName(), []); + const [newCollectionName, setNewCollectionName] = useState(generatedName); + useEffect(() => { dispatch(getCollections(username)).then(() => setHasLoadedData(true)); }, [dispatch, username]); @@ -53,6 +83,17 @@ const AddToCollectionList = ({ projectId }) => { dispatch(removeFromCollection(collection.id, projectId)); }; + const handleCreateCollection = (e) => { + e.preventDefault(); + if (!newCollectionName.trim()) return; + dispatch( + createCollectionAndRefresh({ name: newCollectionName.trim() }, username) + ).then(() => { + setShowCreateForm(false); + setNewCollectionName(generateCollectionName()); + }); + }; + const collectionWithSketchStatus = collections.map((collection) => ({ ...collection, url: `/${collection.owner.username}/collections/${collection.id}`, @@ -63,7 +104,33 @@ const AddToCollectionList = ({ projectId }) => { if (showLoader) { return ; } else if (collections.length === 0) { - return t('AddToCollectionList.Empty'); + return ( +
+ {t('AddToCollectionList.Empty')} + {showCreateForm ? ( + + setNewCollectionName(e.target.value)} + placeholder={generatedName} + aria-label={t('AddToCollectionList.CollectionNameARIA')} + /> + + + ) : ( + + )} +
+ ); } return (