Skip to content

Commit c878b44

Browse files
authored
Merge branch 'develop' into clairep94-patch-pr-template
2 parents 774e8ce + 78ad83a commit c878b44

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1391
-595
lines changed

client/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export const RESET_PROJECT = 'RESET_PROJECT';
3333

3434
export const SET_PROJECT = 'SET_PROJECT';
3535
export const SET_PROJECTS = 'SET_PROJECTS';
36+
export const SET_PROJECTS_FOR_COLLECTION_LIST =
37+
'SET_PROJECTS_FOR_COLLECTION_LIST';
3638

3739
export const SET_COLLECTIONS = 'SET_COLLECTIONS';
3840
export const CREATE_COLLECTION = 'CREATED_COLLECTION';

client/modules/IDE/actions/project.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ export function changeProjectName(id, newName) {
386386
}
387387

388388
export function deleteProject(id) {
389-
return (dispatch, getState) => {
389+
return (dispatch, getState) =>
390390
apiClient
391391
.delete(`/projects/${id}`)
392392
.then(() => {
@@ -411,7 +411,6 @@ export function deleteProject(id) {
411411
});
412412
}
413413
});
414-
};
415414
}
416415
export function changeVisibility(projectId, projectName, visibility, t) {
417416
return (dispatch, getState) => {

client/modules/IDE/actions/projects.js

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,60 @@ import { apiClient } from '../../../utils/apiClient';
22
import * as ActionTypes from '../../../constants';
33
import { startLoader, stopLoader } from '../reducers/loading';
44

5-
// eslint-disable-next-line
6-
export function getProjects(username) {
7-
return (dispatch) => {
8-
dispatch(startLoader());
9-
let url;
10-
if (username) {
11-
url = `/${username}/projects`;
12-
} else {
13-
url = '/projects';
14-
}
15-
return apiClient
16-
.get(url)
17-
.then((response) => {
18-
dispatch({
19-
type: ActionTypes.SET_PROJECTS,
20-
projects: response.data
21-
});
22-
dispatch(stopLoader());
23-
})
24-
.catch((error) => {
25-
dispatch({
26-
type: ActionTypes.ERROR,
27-
error: error?.response?.data
28-
});
29-
dispatch(stopLoader());
30-
});
31-
};
32-
}
5+
const buildProjectsUrl = (username, options = {}) => {
6+
const {
7+
page = 1,
8+
limit = 10,
9+
sortField = 'updatedAt',
10+
sortDir = 'desc',
11+
q = ''
12+
} = options;
13+
14+
const base = username
15+
? `/${encodeURIComponent(username)}/projects`
16+
: '/projects';
17+
18+
const params = new URLSearchParams({
19+
page: String(page),
20+
limit: String(limit),
21+
sortField,
22+
sortDir
23+
});
24+
25+
const trimmed = q.trim();
26+
27+
if (trimmed) {
28+
params.set('q', trimmed);
29+
}
30+
31+
return `${base}?${params.toString()}`;
32+
};
33+
34+
const fetchProjects = (username, options, successType) => (dispatch) => {
35+
dispatch(startLoader());
36+
37+
const url = buildProjectsUrl(username, options);
38+
39+
return apiClient
40+
.get(url)
41+
.then((response) => {
42+
dispatch({ type: successType, projects: response.data });
43+
dispatch(stopLoader());
44+
return response.data;
45+
})
46+
.catch((error) => {
47+
dispatch({ type: ActionTypes.ERROR, error: error?.response?.data });
48+
dispatch(stopLoader());
49+
throw error;
50+
});
51+
};
52+
53+
export const getProjects = (username, options) =>
54+
fetchProjects(username, options, ActionTypes.SET_PROJECTS);
55+
56+
export const getProjectsForCollectionList = (username, options) =>
57+
fetchProjects(
58+
username,
59+
options,
60+
ActionTypes.SET_PROJECTS_FOR_COLLECTION_LIST
61+
);

client/modules/IDE/components/AddToCollectionSketchList.jsx

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { Helmet } from 'react-helmet';
44
import { useDispatch, useSelector } from 'react-redux';
55
import { useTranslation } from 'react-i18next';
66
import { addToCollection, removeFromCollection } from '../actions/collections';
7-
import { getProjects } from '../actions/projects';
8-
import getSortedSketches from '../selectors/projects';
7+
import { getProjectsForCollectionList } from '../actions/projects';
98
import { Loader } from '../../App/components/Loader';
9+
import Pagination from './Pagination';
1010
import QuickAddList from './QuickAddList';
1111
import {
1212
CollectionAddSketchWrapper,
@@ -20,16 +20,39 @@ const AddToCollectionSketchList = ({ collection }) => {
2020

2121
const username = useSelector((state) => state.user.username);
2222

23-
const sketches = useSelector(getSortedSketches);
23+
const sketches = useSelector(
24+
(state) => state.collectionsListProjects.projects
25+
);
26+
27+
const paginationMeta = useSelector(
28+
(state) => state.collectionsListProjects.metadata
29+
);
30+
31+
const q = useSelector((state) => state.search.sketchSearchTerm);
32+
33+
const hasSketches = () => sketches?.length > 0;
34+
35+
const [page, setPage] = useState(1);
36+
const limit = 10;
2437

2538
// TODO: improve loading state
2639
const loading = useSelector((state) => state.loading);
2740
const [hasLoadedData, setHasLoadedData] = useState(false);
2841
const showLoader = loading && !hasLoadedData;
2942

3043
useEffect(() => {
31-
dispatch(getProjects(username)).then(() => setHasLoadedData(true));
32-
}, [dispatch, username]);
44+
dispatch(
45+
getProjectsForCollectionList(username, {
46+
page,
47+
limit,
48+
q
49+
})
50+
).finally(() => setHasLoadedData(true));
51+
}, [dispatch, username, page, q]);
52+
53+
useEffect(() => {
54+
setPage(1);
55+
}, [q]);
3356

3457
const handleCollectionAdd = (sketch) => {
3558
dispatch(addToCollection(collection.id, sketch.id));
@@ -43,7 +66,8 @@ const AddToCollectionSketchList = ({ collection }) => {
4366
...sketch,
4467
url: `/${username}/sketches/${sketch.id}`,
4568
isAdded: collection.items.some(
46-
(item) => item.projectId === sketch.id && !item.isDeleted
69+
(item) =>
70+
(item.projectId || item.project?.id) === sketch.id && !item.isDeleted
4771
)
4872
}));
4973

@@ -55,11 +79,23 @@ const AddToCollectionSketchList = ({ collection }) => {
5579
return t('AddToCollectionSketchList.NoCollections');
5680
}
5781
return (
58-
<QuickAddList
59-
items={sketchesWithAddedStatus}
60-
onAdd={handleCollectionAdd}
61-
onRemove={handleCollectionRemove}
62-
/>
82+
<>
83+
<QuickAddList
84+
items={sketchesWithAddedStatus}
85+
onAdd={handleCollectionAdd}
86+
onRemove={handleCollectionRemove}
87+
/>
88+
{hasSketches() && (
89+
<Pagination
90+
page={page}
91+
totalPages={paginationMeta.totalPages}
92+
onPageChange={setPage}
93+
limit={limit}
94+
totalSketches={paginationMeta.totalProjects}
95+
isOverlay
96+
/>
97+
)}
98+
</>
6399
);
64100
};
65101

@@ -81,7 +117,10 @@ AddToCollectionSketchList.propTypes = {
81117
name: PropTypes.string.isRequired,
82118
items: PropTypes.arrayOf(
83119
PropTypes.shape({
84-
projectId: PropTypes.string.isRequired,
120+
projectId: PropTypes.string,
121+
project: PropTypes.shape({
122+
id: PropTypes.string
123+
}),
85124
isDeleted: PropTypes.bool
86125
})
87126
)

0 commit comments

Comments
 (0)