From 302ed679161f7baa62030fe92652aee9b93ad5a7 Mon Sep 17 00:00:00 2001 From: Hege Aalvik <48259307+hegeaal@users.noreply.github.com> Date: Fri, 20 Oct 2023 15:37:57 +0200 Subject: [PATCH] Feat/add pagination (#1795) --- src/api/community-api/search.ts | 41 +++++++++++----- src/components/with-community/index.tsx | 12 ++--- .../with-community/redux/actions.ts | 16 ++++--- .../with-community/redux/reducer.ts | 7 +-- src/components/with-community/redux/saga.ts | 32 +++++++++---- src/pages/requests/index.tsx | 48 ++++++++++++++++--- src/pages/requests/styled.ts | 37 +++++++++++++- src/types/domain.d.ts | 31 ++++-------- 8 files changed, 154 insertions(+), 70 deletions(-) diff --git a/src/api/community-api/search.ts b/src/api/community-api/search.ts index 2a448818b..c0c03576a 100644 --- a/src/api/community-api/search.ts +++ b/src/api/community-api/search.ts @@ -40,23 +40,38 @@ export const extractTopicsFromSearch = ( return uniqueTopics; }; -export const searchCommunityRequests = ( - queryTerm: string, - sortOption?: string +const buildCommunityRequestsQueryParams = ( + queryTerm: string | undefined, + page: string | undefined, + sortOption: string | undefined ) => { - if (queryTerm.length > 0) { - return axios - .get( - `${FDK_COMMUNITY_BASE_URI}/api/search?term=${queryTerm}&in=titles&matchWords=all&categories[]=6&sortBy=${sortOption}&sortDirection=desc` - ) - .then(({ data }) => data); - } - return axios + const params = new URLSearchParams(); + + if (queryTerm) params.append('term', queryTerm); + if (page) params.append('page', page); + if (sortOption) params.append('sortBy', sortOption); + + return params.toString(); +}; +export const searchCommunityRequests = ( + queryTerm: string | undefined, + page: string | undefined, + sortOption: string | undefined +) => + axios .get( - `${FDK_COMMUNITY_BASE_URI}/api/search?&categories[]=6&sortBy=${sortOption}&sortDirection=desc` + `${FDK_COMMUNITY_BASE_URI}/api/search?categories[]=6&sortDirection=desc&in=titles&matchWords=all&showAs=topics&${buildCommunityRequestsQueryParams( + queryTerm, + page, + sortOption + )}` ) .then(({ data }) => data); -}; + +export const getAllRequests = () => + axios + .get(`${FDK_COMMUNITY_BASE_URI}/api/category/6`) + .then(({ data }) => data); export const pruneNodebbTemplateTags = (raw_text: string) => raw_text.replace( diff --git a/src/components/with-community/index.tsx b/src/components/with-community/index.tsx index 1f60cb002..a2b5ce95b 100644 --- a/src/components/with-community/index.tsx +++ b/src/components/with-community/index.tsx @@ -4,18 +4,15 @@ import { connect } from 'react-redux'; import * as actions from './redux/actions'; -import type { - CommunityPost, - CommunityRequestCategory, - CommunityTopic -} from '../../types'; +import type { CommunityPost, CommunityTopic, Pagination } from '../../types'; export interface Props { topics: CommunityTopic[]; multiplePages: boolean; posts: CommunityPost[]; communityActions: typeof actions; - requests: CommunityRequestCategory; + requests: CommunityTopic[]; + pagination: Pagination; } const withCommunity = (Component: ComponentType) => { @@ -25,7 +22,8 @@ const withCommunity = (Component: ComponentType) => { topics: state.CommunityReducer.get('topics').toJS(), multiplePages: state.CommunityReducer.get('multiplePages'), posts: state.CommunityReducer.get('posts').toJS(), - requests: state.CommunityReducer.get('requests').toJS() + requests: state.CommunityReducer.get('requests').toJS(), + pagination: state.CommunityReducer.get('pagination').toJS() }); const mapDispatchToProps = (dispatch: Dispatch) => ({ diff --git a/src/components/with-community/redux/actions.ts b/src/components/with-community/redux/actions.ts index e92c0ec61..f04935675 100644 --- a/src/components/with-community/redux/actions.ts +++ b/src/components/with-community/redux/actions.ts @@ -12,7 +12,7 @@ import { SEARCH_REQUESTS_FAILED } from './action-types'; -import type { CommunityPost, CommunityTopic } from '../../../types'; +import type { CommunityPost, CommunityTopic, Pagination } from '../../../types'; import { CommunityTerm } from '../../../types/enums'; export function searchTopicsRequested(queryTerm: string) { @@ -47,27 +47,29 @@ export function searchTopicsFailed(message: string) { } export function searchRequestsRequested( - queryTerm: string, - sortOption?: string + queryTerm: string | undefined, + page: string | undefined, + sortOption: string | undefined ) { return { type: SEARCH_REQUESTS_REQUESTED, payload: { queryTerm, + page, sortOption } }; } export function searchRequestsSucceeded( - topics: CommunityTopic[], - multiplePages: boolean + requests: CommunityTopic[], + pagination: Pagination ) { return { type: SEARCH_REQUESTS_SUCCEEDED, payload: { - topics, - multiplePages + requests, + pagination } }; } diff --git a/src/components/with-community/redux/reducer.ts b/src/components/with-community/redux/reducer.ts index 2fe42147a..50705140b 100644 --- a/src/components/with-community/redux/reducer.ts +++ b/src/components/with-community/redux/reducer.ts @@ -21,7 +21,8 @@ const initialState = fromJS({ topics: [], multiplePages: false, posts: [], - requests: {} + requests: [], + pagination: {} }); export default function reducer( @@ -49,8 +50,8 @@ export default function reducer( return state.set('topics', fromJS([])); case SEARCH_REQUESTS_SUCCEEDED: return state - .set('topics', fromJS(action.payload.topics)) - .set('multiplePages', fromJS(action.payload.multiplePages)); + .set('requests', fromJS(action.payload.requests)) + .set('pagination', fromJS(action.payload.pagination)); case SEARCH_REQUESTS_FAILED: default: return state; diff --git a/src/components/with-community/redux/saga.ts b/src/components/with-community/redux/saga.ts index 5a97a9cf7..ba02ab502 100644 --- a/src/components/with-community/redux/saga.ts +++ b/src/components/with-community/redux/saga.ts @@ -9,6 +9,7 @@ import * as actions from './actions'; import { extractTopicsFromSearch, + getAllRequests, getRecentPosts, getTopicById, pruneNodebbTemplateTags, @@ -16,7 +17,11 @@ import { searchCommunityRequests } from '../../../api/community-api/search'; -import type { CommunityPost, CommunityTopic } from '../../../types'; +import type { + CommunityCategory, + CommunityPost, + CommunityTopic +} from '../../../types'; function* searchTopicsRequested({ payload: { queryTerm } @@ -43,30 +48,37 @@ function* searchTopicsRequested({ } function* searchRequestsRequested({ - payload: { queryTerm, sortOption } + payload: { queryTerm, sortOption, page } }: ReturnType) { try { const postHits: CommunityPost = yield call( searchCommunityRequests, queryTerm, + page, sortOption ); - const { multiplePages } = postHits; - const topics: CommunityTopic[] = ( + const { pagination } = postHits; + + const allRequestTopics: CommunityCategory = yield call(getAllRequests); + const { topics } = allRequestTopics; + + const requests: CommunityTopic[] = ( (yield all( - extractTopicsFromSearch(postHits).map(({ tid }) => - call(getTopicById, tid) + postHits.posts.map(({ tid }) => + topics.filter(topic => topic.tid === tid) ) )) as CommunityTopic[] - ).filter(Boolean); + ) + .filter(Boolean) + .flat(); - if (topics.length > 0) { - yield put(actions.searchTopicsSucceeded(topics, multiplePages)); + if (requests.length > 0) { + yield put(actions.searchRequestsSucceeded(requests, pagination)); } else { yield put(actions.searchTopicsFailed('')); } } catch (e: any) { - yield put(actions.searchTopicsFailed(e.message)); + yield put(actions.searchRequestsFailed(e.message)); } } diff --git a/src/pages/requests/index.tsx b/src/pages/requests/index.tsx index 51e45a96d..477b6a97b 100644 --- a/src/pages/requests/index.tsx +++ b/src/pages/requests/index.tsx @@ -3,6 +3,7 @@ import { compose } from 'redux'; import Link from '@fellesdatakatalog/link'; import Button from '@fellesdatakatalog/button'; import Select from 'react-select'; +import ReactPaginate from 'react-paginate'; import withCommunity, { Props as CommunityProps } from '../../components/with-community'; @@ -19,15 +20,17 @@ const { FDK_COMMUNITY_BASE_URI } = env; interface Props extends CommunityProps {} const RequestsPage: FC = ({ - topics, + requests, + pagination, communityActions: { searchRequestsRequested } }) => { useEffect(() => { - searchRequestsRequested(''); + searchRequestsRequested(undefined, '1', undefined); }, []); - const notDeletedRequests = topics?.filter(topic => topic.deleted === 0); - const [search, setSearch] = useState(''); + const notDeletedRequests = requests?.filter(topic => topic.deleted === 0); + const [search, setSearch] = useState(); + const [sortOption, setSortOption] = useState(); const sortOptions: SelectOption[] = [ { @@ -75,7 +78,10 @@ const RequestsPage: FC = ({

{localization.requestsPage.view}