Skip to content

Commit

Permalink
feat: sync url query params
Browse files Browse the repository at this point in the history
  • Loading branch information
g-saracca committed Sep 18, 2024
1 parent 5f7b9d6 commit 50a7c49
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 79 deletions.
26 changes: 4 additions & 22 deletions src/sections/collection/Collection.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Trans, useTranslation } from 'react-i18next'
import { Alert, Col, Row } from '@iqss/dataverse-design-system'
import { Col, Row } from '@iqss/dataverse-design-system'
import { CollectionRepository } from '../../collection/domain/repositories/CollectionRepository'
import { useCollection } from './useCollection'
import { useScrollTop } from '../../shared/hooks/useScrollTop'
import { useSession } from '../session/SessionContext'
import { useGetCollectionUserPermissions } from '../../shared/hooks/useGetCollectionUserPermissions'
import { type UseCollectionQueryParamsReturnType } from './useCollectionQueryParams'
import { type UseCollectionQueryParamsReturnType } from './useGetCollectionQueryParams'
import { BreadcrumbsGenerator } from '../shared/hierarchy/BreadcrumbsGenerator'
import AddDataActionsButton from '../shared/add-data-actions/AddDataActionsButton'
import { CollectionItemsPanel } from './collection-items-panel/CollectionItemsPanel'
import { CollectionInfo } from './CollectionInfo'
import { CollectionSkeleton } from './CollectionSkeleton'
import { PageNotFound } from '../page-not-found/PageNotFound'
import { CreatedAlert } from './CreatedAlert'

interface CollectionProps {
collectionRepository: CollectionRepository
Expand Down Expand Up @@ -41,8 +41,6 @@ export function Collection({

const showAddDataActions = Boolean(user && (canUserAddCollection || canUserAddDataset))

const { t } = useTranslation('collection')

if (!isLoading && !collection) {
return <PageNotFound />
}
Expand All @@ -56,23 +54,7 @@ export function Collection({
<>
<BreadcrumbsGenerator hierarchy={collection.hierarchy} />
<CollectionInfo collection={collection} />
{created && (
<Alert variant="success" dismissible={false}>
<Trans
t={t}
i18nKey="createdAlert"
components={{
anchor: (
<a
href="https://guides.dataverse.org/en/latest/user/dataverse-management.html"
target="_blank"
rel="noreferrer"
/>
)
}}
/>
</Alert>
)}
{created && <CreatedAlert />}
</>
)}
<CollectionItemsPanel
Expand Down
4 changes: 2 additions & 2 deletions src/sections/collection/CollectionFactory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useLocation, useParams } from 'react-router-dom'
import { CollectionJSDataverseRepository } from '../../collection/infrastructure/repositories/CollectionJSDataverseRepository'
import { Collection } from './Collection'
import { INFINITE_SCROLL_ENABLED } from './config'
import { useCollectionQueryParams } from './useCollectionQueryParams'
import { useGetCollectionQueryParams } from './useGetCollectionQueryParams'

const collectionRepository = new CollectionJSDataverseRepository()
export class CollectionFactory {
Expand All @@ -13,7 +13,7 @@ export class CollectionFactory {
}

function CollectionWithSearchParams() {
const collectionQueryParams = useCollectionQueryParams()
const collectionQueryParams = useGetCollectionQueryParams()
const { collectionId = 'root' } = useParams<{ collectionId: string }>()
const location = useLocation()
const state = location.state as { created: boolean } | undefined
Expand Down
23 changes: 23 additions & 0 deletions src/sections/collection/CreatedAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Alert } from '@iqss/dataverse-design-system'
import { Trans, useTranslation } from 'react-i18next'

export const CreatedAlert = () => {
const { t } = useTranslation('collection')
return (
<Alert variant="success" dismissible={false}>
<Trans
t={t}
i18nKey="createdAlert"
components={{
anchor: (
<a
href="https://guides.dataverse.org/en/latest/user/dataverse-management.html"
target="_blank"
rel="noreferrer"
/>
)
}}
/>
</Alert>
)
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { useEffect, useRef, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { CollectionRepository } from '../../../collection/domain/repositories/CollectionRepository'
import { CollectionItemsPaginationInfo } from '../../../collection/domain/models/CollectionItemsPaginationInfo'
import { CollectionSearchCriteria } from '../../../collection/domain/models/CollectionSearchCriteria'
import { useGetAccumulatedItems } from './useGetAccumulatedItems'
import { UseCollectionQueryParamsReturnType } from '../useCollectionQueryParams'
import { UseCollectionQueryParamsReturnType } from '../useGetCollectionQueryParams'
import { useLoading } from '../../loading/LoadingContext'
import { FilterPanel } from './filter-panel/FilterPanel'
import { ItemsList } from './items-list/ItemsList'
import { SearchPanel } from './search-panel/SearchPanel'
import { QueryParamKey } from '../../Route.enum'
import { CollectionItemType } from '../../../collection/domain/models/CollectionItemType'
import { ItemTypeChange } from './filter-panel/type-filters/TypeFilters'
import styles from './CollectionItemsPanel.module.scss'

interface ItemsPanelProps {
interface CollectionItemsPanelProps {
collectionId: string
collectionRepository: CollectionRepository
collectionQueryParams: UseCollectionQueryParamsReturnType
Expand All @@ -22,19 +26,20 @@ export const CollectionItemsPanel = ({
collectionRepository,
collectionQueryParams,
addDataSlot
}: ItemsPanelProps) => {
}: CollectionItemsPanelProps) => {
const { setIsLoading } = useLoading()
const [_, setSearchParams] = useSearchParams()

const initialSearchCriteria = new CollectionSearchCriteria(
// This object will update every time we update a query param in the URL with the setSearchParams setter
const currentSearchCriteria = new CollectionSearchCriteria(
collectionQueryParams.searchQuery,
collectionQueryParams.typesQuery
collectionQueryParams.typesQuery || [CollectionItemType.COLLECTION, CollectionItemType.DATASET]
)

console.log({ initialSearchCriteria })

const [searchCriteria, setSearchCriteria] =
useState<CollectionSearchCriteria>(initialSearchCriteria)

/*
TODO:ME For now I think we really shouldnt care about setting an inital page based on the page query param
Items in specific page of a list could change while browsing at different times so is not so useful for url sharing.
*/
const [paginationInfo, setPaginationInfo] = useState<CollectionItemsPaginationInfo>(
new CollectionItemsPaginationInfo()
)
Expand All @@ -60,25 +65,86 @@ export const CollectionItemsPanel = ({
if (totalAvailable !== undefined) {
paginationInfoToSend = currentPagination.goToNextPage()
}
console.log('paginationInfoToSend', paginationInfoToSend)
const totalItemsCount = await loadMore(paginationInfoToSend, searchCriteria)

const totalItemsCount = await loadMore(paginationInfoToSend, currentSearchCriteria)

if (totalItemsCount !== undefined) {
const paginationInfoUpdated = paginationInfoToSend.withTotal(totalItemsCount)
setPaginationInfo(paginationInfoUpdated)
}
}

// This function is called when the user changes the search criteria (search input, filters, etc.)
const handleCriteriaChange = async (newCriteria: CollectionSearchCriteria) => {
const handleSearchSubmit = async (searchValue: string) => {
itemsListContainerRef.current?.scrollTo({ top: 0 })

setSearchCriteria(newCriteria)
const resetedPaginationInfo = new CollectionItemsPaginationInfo()
setPaginationInfo(resetedPaginationInfo)

if (searchValue === '') {
// Update the URL without the search value, keep other querys
setSearchParams((currentSearchParams) => {
currentSearchParams.delete(QueryParamKey.QUERY)
return currentSearchParams
})
} else {
// Update the URL with the search value ,keep other querys and include all item types always
setSearchParams((currentSearchParams) => ({
...currentSearchParams,
[QueryParamKey.COLLECTION_ITEM_TYPES]: [
CollectionItemType.COLLECTION,
CollectionItemType.DATASET,
CollectionItemType.FILE
].join(','),
[QueryParamKey.QUERY]: searchValue
}))
}

// WHEN SEARCHING, WE RESET THE PAGINATION INFO AND KEEP ALL ITEM TYPES!!
const newCollectionSearchCriteria = new CollectionSearchCriteria(
searchValue === '' ? undefined : searchValue,
[CollectionItemType.COLLECTION, CollectionItemType.DATASET, CollectionItemType.FILE]
)

const totalItemsCount = await loadMore(resetedPaginationInfo, newCollectionSearchCriteria, true)

if (totalItemsCount !== undefined) {
const paginationInfoUpdated = resetedPaginationInfo.withTotal(totalItemsCount)
setPaginationInfo(paginationInfoUpdated)
}
}

// WHEN APPLYING FILTERS, WE RESET THE PAGINATION INFO AND IF SEARCH VALUE EXISTS, WE KEEP IT!!
const handleItemsTypeChange = async (itemTypeChange: ItemTypeChange) => {
console.log({ itemTypeChange })
const { type, checked } = itemTypeChange

const newItemsTypes = checked
? [...new Set([...(currentSearchCriteria?.itemTypes ?? []), type])]
: (currentSearchCriteria.itemTypes ?? []).filter((itemType) => itemType !== type)

console.log({ newItemsTypes })
// KEEP SEARCH VALUE IF EXISTS
itemsListContainerRef.current?.scrollTo({ top: 0 })

const resetedPaginationInfo = new CollectionItemsPaginationInfo()
setPaginationInfo(resetedPaginationInfo)

const totalItemsCount = await loadMore(resetedPaginationInfo, newCriteria, true)
// Update the URL with the new item types, keep other querys and include the search value if exists
setSearchParams((currentSearchParams) => ({
...currentSearchParams,
[QueryParamKey.COLLECTION_ITEM_TYPES]: newItemsTypes.join(','),
...(currentSearchCriteria.searchText && {
[QueryParamKey.QUERY]: currentSearchCriteria.searchText
})
}))

const newCollectionSearchCriteria = new CollectionSearchCriteria(
currentSearchCriteria.searchText,
newItemsTypes
)

const totalItemsCount = await loadMore(resetedPaginationInfo, newCollectionSearchCriteria, true)

if (totalItemsCount !== undefined) {
const paginationInfoUpdated = resetedPaginationInfo.withTotal(totalItemsCount)
setPaginationInfo(paginationInfoUpdated)
Expand All @@ -92,12 +158,20 @@ export const CollectionItemsPanel = ({
return (
<section className={styles['items-panel']}>
<header className={styles['top-wrapper']}>
<SearchPanel />
<SearchPanel
onSubmitSearch={handleSearchSubmit}
initialSearchValue={currentSearchCriteria.searchText}
isLoadingCollectionItems={isLoadingItems}
/>
<div className={styles['add-data-slot']}>{addDataSlot}</div>
</header>

<div className={styles['bottom-wrapper']}>
<FilterPanel />
<FilterPanel
currentItemTypes={currentSearchCriteria.itemTypes}
onItemTypesChange={handleItemsTypeChange}
isLoadingCollectionItems={isLoadingItems}
/>

<ItemsList
items={accumulatedItems}
Expand All @@ -107,7 +181,9 @@ export const CollectionItemsPanel = ({
areItemsAvailable={areItemsAvailable}
hasNextPage={hasNextPage}
isEmptyItems={isEmptyItems}
hasSearchValue={searchCriteria.hasSearchText()}
hasSearchValue={new CollectionSearchCriteria(
collectionQueryParams.searchQuery
).hasSearchText()}
paginationInfo={paginationInfo}
onLoadMore={handleOnLoadMore}
ref={itemsListContainerRef}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// TODO:ME Delete if not needed
export class CollectionItemsPanelHelper {
// static getURLQueryValueByKey(queryKey: string): string | null {
// const searchParams = new URLSearchParams(window.location.search)
// return searchParams.get(queryKey)
// }
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { useState } from 'react'
import { Button, Offcanvas } from '@iqss/dataverse-design-system'
import { FunnelFill } from 'react-bootstrap-icons'
import { TypeFilters } from './type-filters/TypeFilters'
import { ItemTypeChange, TypeFilters } from './type-filters/TypeFilters'
import { CollectionItemType } from '../../../../collection/domain/models/CollectionItemType'
import styles from './FilterPanel.module.scss'

export const FilterPanel = () => {
interface FilterPanelProps {
currentItemTypes?: CollectionItemType[]
onItemTypesChange: (itemTypeChange: ItemTypeChange) => void
isLoadingCollectionItems: boolean
}

export const FilterPanel = ({
currentItemTypes,
onItemTypesChange,
isLoadingCollectionItems
}: FilterPanelProps) => {
const [showOffcanvas, setShowOffcanvas] = useState(false)

const handleCloseOffcanvas = () => setShowOffcanvas(false)
Expand All @@ -26,7 +37,11 @@ export const FilterPanel = () => {
</Offcanvas.Header>
<Offcanvas.Body>
<div className={styles['filters-wrapper']}>
<TypeFilters />
<TypeFilters
onItemTypesChange={onItemTypesChange}
currentItemTypes={currentItemTypes}
isLoadingCollectionItems={isLoadingCollectionItems}
/>
</div>
</Offcanvas.Body>
</Offcanvas>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@
input[type='checkbox'] {
cursor: pointer;

& + label {
color: $dv-primary-color;
cursor: pointer;
}

&:checked + label {
font-weight: 500;
}
}

.label-content-wrapper {
color: $dv-primary-color;
cursor: pointer;
&:disabled {
opacity: 0.7;

& + label {
opacity: 0.7;
}
}
}
}
Loading

0 comments on commit 50a7c49

Please sign in to comment.