@@ -12,9 +12,9 @@ import React, { useCallback, useState } from 'react'
1212import pluralize from 'pluralize'
1313
1414import Button from '@/js/components/Button/Button'
15+ import ControlledPaginatedContent from '@/js/components/ControlledPaginatedContent/ControlledPaginatedContent'
1516import CustomModal from '@/js/components/CustomModal/CustomModal'
1617import EllipsisText from '@/js/components/EllipsisText/EllipsisText'
17- import Pagination from '@/js/components/Pagination/Pagination'
1818import Table from '@/js/components/Table/Table'
1919
2020import conceptTypeQueries from '@/js/constants/conceptTypeQueries'
@@ -41,14 +41,17 @@ const ManageCollectionAssociation = () => {
4141
4242 const { addNotification } = useNotificationsContext ( )
4343
44- const [ searchParams , setSearchParams ] = useSearchParams ( )
44+ const derivedConceptType = getConceptTypeByConceptId ( conceptId )
45+
46+ // Variables for deletion mutation
4547 const [ collectionConceptIds , setCollectionConceptIds ] = useState ( [ ] )
4648 const [ showDeleteModal , setShowDeleteModal ] = useState ( false )
49+ const [ isDeleting , setIsDeleting ] = useState ( false )
4750
48- const derivedConceptType = getConceptTypeByConceptId ( conceptId )
49-
51+ // Variables for pagination
52+ const [ searchParams , setSearchParams ] = useSearchParams ( )
53+ const [ activePage , setActivePage ] = useState ( 1 )
5054 const limit = 20
51- const activePage = parseInt ( searchParams . get ( 'page' ) , 10 ) || 1
5255 const offset = ( activePage - 1 ) * limit
5356
5457 let params = {
@@ -79,10 +82,7 @@ const ManageCollectionAssociation = () => {
7982 } )
8083
8184 const [ deleteAssociationMutation ] = useMutation ( DELETE_ASSOCIATION , {
82- refetchQueries : [ {
83- query : conceptTypeQueries [ derivedConceptType ] ,
84- variables : params
85- } ] ,
85+
8686 onCompleted : ( ) => {
8787 setShowDeleteModal ( false )
8888
@@ -93,8 +93,14 @@ const ManageCollectionAssociation = () => {
9393 } )
9494
9595 setCollectionConceptIds ( [ ] )
96+
97+ // Gives time for CMR to update data
98+ setTimeout ( ( ) => {
99+ refetch ( )
100+ } , 250 )
96101 } ,
97102 onError : ( ) => {
103+ setShowDeleteModal ( false )
98104 addNotification ( {
99105 message : 'Error disassociating collection' ,
100106 variant : 'danger'
@@ -105,13 +111,15 @@ const ManageCollectionAssociation = () => {
105111 } )
106112
107113 // Handles deleting selected collection
108- // if no collections selected, returns an error notification
109114 const handleDeleteAssociation = ( ) => {
115+ setIsDeleting ( true )
110116 deleteAssociationMutation ( {
111117 variables : {
112118 conceptId,
113119 associatedConceptIds : collectionConceptIds
114120 }
121+ } ) . finally ( ( ) => {
122+ setIsDeleting ( false )
115123 } )
116124 }
117125
@@ -124,14 +132,13 @@ const ManageCollectionAssociation = () => {
124132 if ( order === 'ascending' ) nextSortKey = `-${ key } `
125133 if ( order === 'descending' ) nextSortKey = key
126134
127- // Reset the page parameter
128- currentParams . delete ( 'page' )
129-
130135 // Set the sort key
131136 currentParams . set ( 'sortKey' , nextSortKey )
132137
133138 return Object . fromEntries ( currentParams )
134139 } )
140+
141+ setActivePage ( 1 ) // Reset to first page when sorting
135142 } , [ ] )
136143
137144 const buildEllipsisTextCell = useCallback ( ( cellData ) => (
@@ -140,8 +147,8 @@ const ManageCollectionAssociation = () => {
140147 </ EllipsisText >
141148 ) , [ ] )
142149
143- // Handles checkbox selections, if checked add the conceptId to the state variable
144- // and pops the added conceptId from the array.
150+ // Adds or removes checked collections from collectionConceptIds array
151+ // which is provided to the deleteMutation
145152 const handleCheckbox = ( event ) => {
146153 const { target } = event
147154 const { value } = target
@@ -200,11 +207,7 @@ const ManageCollectionAssociation = () => {
200207 ]
201208
202209 const setPage = ( nextPage ) => {
203- setSearchParams ( ( currentParams ) => {
204- currentParams . set ( 'page' , nextPage )
205-
206- return Object . fromEntries ( currentParams )
207- } )
210+ setActivePage ( nextPage )
208211 }
209212
210213 const toggleShowDeleteModal = ( nextState ) => {
@@ -216,91 +219,101 @@ const ManageCollectionAssociation = () => {
216219 toggleShowDeleteModal ( true )
217220 } )
218221
219- // Handle refresh, calls getMetadata to get the list of association
220- // TODO: MMT-4089 See if we can get rid of this refresh button.
221- const handleRefreshPage = ( ) => {
222- refetch ( )
223- }
224-
225- const refreshAccessibleEventProps = useAccessibleEvent ( ( ) => {
226- handleRefreshPage ( )
227- } )
228-
229222 const { [ camelCase ( derivedConceptType ) ] : concept } = data
230223
231224 const { collections : associatedCollections } = concept
232225
233- const { items = [ ] , count } = associatedCollections
234-
235- const totalPages = Math . ceil ( count / limit )
236-
237- const currentPageIndex = Math . floor ( offset / limit )
238- const firstResultIndex = currentPageIndex * limit
239- const isLastPage = totalPages === activePage
240- const lastResultIndex = firstResultIndex + ( isLastPage ? count % limit : limit )
241-
242- const paginationMessage = count > 0
243- ? `Showing ${ totalPages > 1 ? `Collection Associations ${ firstResultIndex + 1 } -${ lastResultIndex } of ${ count } ` : `${ count } ${ pluralize ( 'Collection Association' , count ) } ` } `
244- : 'No Collection Associations found'
226+ const { items, count } = associatedCollections
245227
246228 return (
247- < div className = "mt-4" >
229+ < div >
248230 < Alert className = "fst-italic fs-6" variant = "warning" >
249231 < i className = "eui-icon eui-fa-info-circle" />
250232 { ' ' }
251233 Association operations may take some time. If you are not seeing what you expect below,
252234 please
253235 { ' ' }
254- < span
255- className = "text-decoration-underline"
236+ < button
237+ className = "btn btn-link p-0 text-decoration-underline"
256238 style = {
257239 {
258240 color : 'blue' ,
259241 cursor : 'pointer'
260242 }
261243 }
262- // eslint-disable-next-line react/jsx-props-no-spreading
263- { ...refreshAccessibleEventProps }
244+ onClick = { ( ) => refetch ( ) }
245+ aria-label = "Refresh the page"
246+ type = "button"
264247 >
265- refresh the page
266- </ span >
248+ < i > refresh the page</ i >
249+ </ button >
267250 </ Alert >
268- < Row className = "d-flex justify-content-between align-items-center mb-4 mt-5" >
269- < Col className = "mb-4 flex-grow-1" xs = "auto" >
270- {
271- ( ! ! count ) && (
272- < span className = "text-secondary fw-bolder" > { paginationMessage } </ span >
251+ < ControlledPaginatedContent
252+ activePage = { activePage }
253+ count = { count }
254+ limit = { limit }
255+ setPage = { setPage }
256+ >
257+ {
258+ ( {
259+ totalPages,
260+ pagination,
261+ firstResultPosition,
262+ lastResultPosition
263+ } ) => {
264+ const paginationMessage = count > 0
265+ ? `Showing ${ totalPages > 1 ? `${ firstResultPosition } -${ lastResultPosition } of` : '' } ${ count } Collection ${ pluralize ( 'Association' , count ) } `
266+ : 'No collection associations found'
267+
268+ return (
269+ < >
270+ < Row className = "d-flex justify-content-between align-items-center mb-4" >
271+ < Col className = "mb-4 flex-grow-1" xs = "auto" >
272+ {
273+ ( ! ! count ) && (
274+ < span className = "text-secondary fw-bolder" > { paginationMessage } </ span >
275+ )
276+ }
277+ </ Col >
278+ < Col className = "mb-4 flex-grow-1" xs = "auto" />
279+ {
280+ totalPages > 1 && (
281+ < Col xs = "auto" >
282+ { pagination }
283+ </ Col >
284+ )
285+ }
286+ </ Row >
287+ < Table
288+ className = "m-5"
289+ columns = { columns }
290+ data = { items }
291+ generateCellKey = { ( { conceptId : conceptIdCell } , dataKey ) => `column_${ dataKey } _${ conceptIdCell } ` }
292+ generateRowKey = { ( { conceptId : conceptIdRow } ) => `row_${ conceptIdRow } ` }
293+ id = "associated-collections"
294+ limit = { count }
295+ noDataMessage = "No collection associations found."
296+ />
297+ {
298+ totalPages > 1 && (
299+ < Row >
300+ < Col xs = "12" className = "pt-4 d-flex align-items-center justify-content-center" >
301+ < div >
302+ { pagination }
303+ </ div >
304+ </ Col >
305+ </ Row >
306+ )
307+ }
308+ </ >
273309 )
274310 }
275- </ Col >
276- {
277- totalPages > 1 && (
278- < Col xs = "auto" >
279- < Pagination
280- setPage = { setPage }
281- activePage = { activePage }
282- totalPages = { totalPages }
283- />
284- </ Col >
285- )
286311 }
287- </ Row >
288- < Table
289- className = "m-5"
290- columns = { columns }
291- data = { items }
292- generateCellKey = { ( { conceptId : conceptIdCell } , dataKey ) => `column_${ dataKey } _${ conceptIdCell } ` }
293- generateRowKey = { ( { conceptId : conceptIdRow } ) => `row_${ conceptIdRow } ` }
294- id = "associated-collections"
295- limit = { count }
296- noDataMessage = "No collection associations found."
297- offset = { offset }
298- />
312+ </ ControlledPaginatedContent >
299313 < Button
300314 className = "mt-4"
301315 variant = "danger"
302- disabled = { collectionConceptIds . length === 0 }
303- // eslint-disable-next-line react/jsx-props-no-spreading
316+ disabled = { collectionConceptIds . length === 0 || isDeleting }
304317 { ...accessibleEventProps }
305318 >
306319 Delete Selected Associations
@@ -319,7 +332,8 @@ const ManageCollectionAssociation = () => {
319332 {
320333 label : 'Yes' ,
321334 variant : 'primary' ,
322- onClick : handleDeleteAssociation
335+ onClick : handleDeleteAssociation ,
336+ disabled : isDeleting
323337 }
324338 ]
325339 }
0 commit comments