Skip to content

Commit 2267e81

Browse files
ABee-Techlmmrssa
andauthored
library grouped pagination (connects #390) (#419)
Co-authored-by: Laxman Maharjan <email@mlaxman.com.np>
1 parent f44df6d commit 2267e81

File tree

7 files changed

+114
-99
lines changed

7 files changed

+114
-99
lines changed

api/src/controllers/resourceController.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,25 @@ const Resource = require('../models/resourceModel.js')
22
const Sequelize = require('sequelize')
33
const Op = Sequelize.Op
44
const { changeFormat } = require('../helpers/filehelpers')
5+
const { where } = require('sequelize')
56

67
// @desc Fetch all resources
7-
// @route GET /api/resources
8+
// @route GET /api/resources?pageNumber=${pageNumber}&category=${category}
89
// @access Public
910
const getResources = (req, res) => {
1011
const pageSize = 5
1112
const page = Number(req.query.pageNumber) || 1
13+
const { category, search } = req.query
1214
const order = req.query.order || 'ASC'
1315
const ordervalue = order && [['title', order]]
1416
Resource.findAndCountAll({
1517
offset: (page - 1) * pageSize,
1618
limit: pageSize,
17-
ordervalue
19+
ordervalue,
20+
where: {
21+
...(search ? { title: { [Op.iLike]: '%' + search + '%' } } : {}),
22+
...(category ? { resourceType: category } : {})
23+
}
1824
})
1925
.then((resources) => {
2026
const totalPages = Math.ceil(resources.count / pageSize)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
'use strict'
2+
3+
module.exports = {
4+
up: async (queryInterface, Sequelize) => {
5+
await queryInterface.removeColumn('resources', 'resourceFor')
6+
await queryInterface.removeColumn('resources', 'publisher')
7+
await queryInterface.removeColumn('resources', 'linkToLicense')
8+
await queryInterface.removeColumn('resources', 'uploadDate')
9+
await queryInterface.removeColumn('resources', 'addedBy')
10+
await queryInterface.removeColumn('resources', 'openWith')
11+
await queryInterface.removeColumn('resources', 'subject')
12+
await queryInterface.removeColumn('resources', 'articleDate')
13+
await queryInterface.removeColumn('resources', 'kind')
14+
await queryInterface.removeColumn('resources', 'language')
15+
await queryInterface.removeColumn('resources', 'author')
16+
await queryInterface.removeColumn('resources', 'sum')
17+
await queryInterface.removeColumn('resources', 'level')
18+
await queryInterface.removeColumn('resources', 'languages')
19+
await queryInterface.removeColumn('resources', 'timesRated')
20+
await queryInterface.removeColumn('resources', 'tag')
21+
await queryInterface.removeColumn('resources', 'year')
22+
await queryInterface.removeColumn('resources', 'averageRating')
23+
await queryInterface.removeColumn('resources', 'mediaType')
24+
await queryInterface.removeColumn('resources', 'tags')
25+
await queryInterface.removeColumn('resources', 'medium')
26+
await queryInterface.removeColumn('resources', 'isDownloadable')
27+
await queryInterface.removeColumn('resources', 'openUrl')
28+
await queryInterface.removeColumn('resources', 'attachments')
29+
await queryInterface.renameColumn('resources', 'createdDate', 'createdAt')
30+
await queryInterface.renameColumn('resources', 'updatedDate', 'updatedAt')
31+
},
32+
33+
down: async (queryInterface, Sequelize) => {
34+
await queryInterface.addColumn('resources', 'resourceFor', { type: Sequelize.TEXT })
35+
await queryInterface.addColumn('resources', 'publisher', { type: Sequelize.STRING })
36+
await queryInterface.addColumn('resources', 'linkToLicense', { type: Sequelize.STRING })
37+
await queryInterface.addColumn('resources', 'uploadDate', { type: Sequelize.DATE })
38+
await queryInterface.addColumn('resources', 'addedBy', { type: Sequelize.STRING })
39+
await queryInterface.addColumn('resources', 'openWith', { type: Sequelize.STRING })
40+
await queryInterface.addColumn('resources', 'subject', { type: Sequelize.TEXT })
41+
await queryInterface.addColumn('resources', 'articleDate', { type: Sequelize.DATE })
42+
await queryInterface.addColumn('resources', 'kind', { type: Sequelize.STRING })
43+
await queryInterface.addColumn('resources', 'language', { type: Sequelize.STRING })
44+
await queryInterface.addColumn('resources', 'author', { type: Sequelize.STRING })
45+
await queryInterface.addColumn('resources', 'sum', { type: Sequelize.DOUBLE })
46+
await queryInterface.addColumn('resources', 'level', { type: Sequelize.TEXT })
47+
await queryInterface.addColumn('resources', 'languages', { type: Sequelize.TEXT })
48+
await queryInterface.addColumn('resources', 'timesRated', { type: Sequelize.STRING })
49+
await queryInterface.addColumn('resources', 'tag', { type: Sequelize.TEXT })
50+
await queryInterface.addColumn('resources', 'year', { type: Sequelize.DATE })
51+
await queryInterface.addColumn('resources', 'averageRating', { type: Sequelize.DOUBLE })
52+
await queryInterface.addColumn('resources', 'mediaType', { type: Sequelize.STRING })
53+
await queryInterface.addColumn('resources', 'tags', { type: Sequelize.STRING })
54+
await queryInterface.addColumn('resources', 'medium', { type: Sequelize.STRING })
55+
await queryInterface.addColumn('resources', 'isDownloadable', { type: Sequelize.BOOLEAN })
56+
await queryInterface.addColumn('resources', 'openUrl', { type: Sequelize.STRING })
57+
await queryInterface.addColumn('resources', 'attachments', { type: Sequelize.TEXT })
58+
await queryInterface.renameColumn('resources', 'createdAt', 'createdDate')
59+
await queryInterface.renameColumn('resources', 'updatedAt', 'updatedDate')
60+
}
61+
}

api/src/models/resourceModel.js

Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,89 +6,17 @@ const Resources = db.define('resources',
66
title: {
77
type: Sequelize.TEXT
88
},
9-
resourceFor: {
10-
type: Sequelize.TEXT
11-
},
12-
publisher: {
13-
type: Sequelize.STRING
14-
},
15-
linkToLicense: {
16-
type: Sequelize.STRING
17-
},
18-
uploadDate: {
19-
type: Sequelize.DATE
20-
},
21-
addedBy: {
22-
type: Sequelize.STRING
23-
},
24-
openWith: {
25-
type: Sequelize.STRING
26-
},
27-
subject: {
28-
type: Sequelize.TEXT
29-
},
30-
articleDate: {
31-
type: Sequelize.DATE
32-
},
33-
kind: {
34-
type: Sequelize.STRING
35-
},
36-
language: {
37-
type: Sequelize.STRING
38-
},
39-
author: {
40-
type: Sequelize.STRING
41-
},
42-
sum: {
43-
type: Sequelize.DOUBLE
44-
},
45-
level: {
46-
type: Sequelize.TEXT
47-
},
48-
languages: {
49-
type: Sequelize.TEXT
50-
},
51-
timesRated: {
52-
type: Sequelize.STRING
53-
},
54-
tag: {
55-
type: Sequelize.TEXT
56-
},
57-
year: {
58-
type: Sequelize.DATE
59-
},
60-
averageRating: {
61-
type: Sequelize.DOUBLE
62-
},
639
filename: {
6410
type: Sequelize.STRING
6511
},
66-
mediaType: {
67-
type: Sequelize.STRING
68-
},
6912
description: {
7013
type: Sequelize.TEXT
7114
},
72-
tags: {
73-
type: Sequelize.STRING
74-
},
75-
medium: {
76-
type: Sequelize.STRING
77-
},
78-
isDownloadable: {
79-
type: Sequelize.BOOLEAN
80-
},
8115
resourceType: {
8216
type: Sequelize.STRING
83-
},
84-
openUrl: {
85-
type: Sequelize.STRING
86-
},
87-
attachments: {
88-
type: Sequelize.TEXT
8917
}
9018
},
91-
{ timestamps: false }
19+
{ timestamps: true }
9220
)
9321

9422
module.exports = Resources

src/actions/resourceActions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export const createResource = (newResource) => async (dispatch, getState) => {
4949
formData.append('title', newResource.title)
5050
formData.append('description', newResource.description)
5151
formData.append('file', newResource.file)
52+
formData.append('resourceType', newResource.resourceType || 'articles')
5253
try {
5354
dispatch({ type: RESOURCE_CREATE_REQUEST })
5455
const { userLogin: { userInfo } } = getState()

src/screens/library/Library.jsx

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,31 @@ import SimpleModal from '../../components/simpleModal/SimpleModal'
66
import CollectionModal from '../../components/collectionModal/CollectionModal'
77
import GroupModal from '../../components/groupModal/GroupModal'
88
import { groupCollection, nav } from './CollectionData'
9-
import { useSelector, useDispatch } from 'react-redux'
10-
import { listResources, searchResources } from '../../actions/resourceActions'
9+
import { useSelector } from 'react-redux'
1110
import Pagination from '../../components/pagination/Pagination'
1211
import SubHeader from '../../components/subHeader/SubHeader'
1312
import { useHistory } from 'react-router-dom'
13+
import useGetFetchData from '../../utils/useGetFetchData'
14+
import { GET_LIBRARY } from '../../utils/urlConstants'
1415

1516
const Library = () => {
16-
const resourceList = useSelector((state) => state.listResources)
17-
const data = useSelector((state) => state.listResources)
18-
let resources = resourceList.searchResources ? resourceList.searchResources : resourceList.resources
19-
if (data) resources = data.resources
2017
const userLogin = useSelector((state) => state.userLogin)
2118
const { userInfo } = userLogin
2219
const history = useHistory()
2320

2421
const [newCollection, setNewCollection] = useState(false)
2522
const [active, setActive] = useState(false)
2623
const [modalActive, setModalActive] = useState(false)
27-
const [pageNumber, setPageNumber] = useState(1)
28-
const [search, setSearch] = useState(null)
29-
const dispatch = useDispatch()
24+
const [search, setSearch] = useState()
3025

3126
function openAddCollection () {
3227
setModalActive(true)
3328
setActive(false)
3429
}
3530

3631
useEffect(() => {
37-
if (!userInfo) {
38-
history.push('/login')
39-
}
40-
if (search) dispatch(searchResources(search))
41-
if (!search) dispatch(listResources('', pageNumber))
42-
}, [search, dispatch, history, userInfo, pageNumber])
32+
if (!userInfo) history.push('/login')
33+
}, [search, history, userInfo])
4334

4435
return (
4536
<>
@@ -48,23 +39,21 @@ const Library = () => {
4839
data={groupCollection} btnName='add to collections'
4940
setNewCollection={setNewCollection}
5041
/>}
51-
5242
{newCollection && <SimpleModal setNewCollection={setNewCollection} />}
53-
5443
{active && <CollectionModal setActive={setActive} openAddCollection={openAddCollection} />}
5544

5645
<DashboardLayout title='Library'>
5746
<div className='library-main-container'>
5847
<SubHeader search={search} setSearch={setSearch} nav={nav} setCreateActive={setActive} btnName='Add files' />
5948
{['Articles', 'Videos'].map(type => (
60-
<div className='list-container'>
61-
<ListView
62-
title={type} data={resources}
49+
<div className='list-container' key={type}>
50+
<LibraryCategory
51+
search={search}
52+
title={type}
6353
setNewCollection={setNewCollection}
6454
modalActive={modalActive}
6555
setModalActive={setModalActive}
6656
/>
67-
<Pagination pageNumber={pageNumber} setPageNumber={setPageNumber} resourceList={resourceList} />
6857
</div>
6958
))}
7059
</div>
@@ -73,4 +62,31 @@ const Library = () => {
7362
)
7463
}
7564

65+
const LibraryCategory = ({ title, search, setNewCollection, modalActive, setModalActive }) => {
66+
const [pageNumber, setPageNumber] = useState(1)
67+
useEffect(() => {
68+
setPageNumber(1)
69+
}, [search])
70+
const { data: libraryData, isLoading } = useGetFetchData(
71+
'LIBRARY_CATEGORY_DATA',
72+
GET_LIBRARY + '?pageNumber=' + pageNumber + '&category=' + title.toLowerCase() + '&search=' + (search || ''),
73+
{ title, pageNumber, search }
74+
)
75+
if (isLoading) {
76+
return (<div>Loading...</div>)
77+
}
78+
return (
79+
libraryData?.resources.length > 0
80+
? <>
81+
<ListView
82+
title={title} data={libraryData?.resources}
83+
setNewCollection={setNewCollection}
84+
modalActive={modalActive}
85+
setModalActive={setModalActive}
86+
/>
87+
<Pagination pageNumber={pageNumber} setPageNumber={setPageNumber} resourceList={libraryData} />
88+
</> : <></>
89+
)
90+
}
91+
7692
export default Library

src/utils/urlConstants.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export const Axios = axios.create({
1010
// categories
1111
export const CATEGORY = BASE_URL + 'categories'
1212

13+
// library
14+
export const GET_LIBRARY = BASE_URL + 'resources'
15+
1316
// course
1417
export const GET_COURSE = BASE_URL + 'courses'
1518
export const ADD_COURSE = BASE_URL + 'courses/add'

src/utils/useGetFetchData.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import axios from 'axios'
22
import { useQuery } from 'react-query'
33
import { configFunc } from './apiFunc'
44

5-
const useGetFetchData = (uniqueKey, url) => {
6-
const { error, isLoading, data } = useQuery(uniqueKey, async () => {
5+
const useGetFetchData = (uniqueKey, url, dependencies) => {
6+
const { error, isLoading, data } = useQuery([uniqueKey, { ...dependencies }], async () => {
77
const { data } = await axios.get(url, configFunc())
88
return data
9-
})
9+
}, { keepPreviousData: true })
1010
return { data, error, isLoading }
1111
}
1212

0 commit comments

Comments
 (0)