import { styled } from '@mui/material/styles'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { translate } from 'react-polyglot'; import { connect } from 'react-redux'; import { changeViewStyle as changeViewStyleAction, filterByField as filterByFieldAction, groupByField as groupByFieldAction, sortByField as sortByFieldAction, } from '../../actions/entries'; import { components } from '../../components/UI/styles'; import { SortDirection } from '../../interface'; import { getNewEntryUrl } from '../../lib/urlHelper'; import { selectSortableFields, selectViewFilters, selectViewGroups, } from '../../lib/util/collection.util'; import { selectEntriesFilter, selectEntriesGroup, selectEntriesSort, selectViewStyle, } from '../../reducers/entries'; import CollectionControls from './CollectionControls'; import CollectionTop from './CollectionTop'; import EntriesCollection from './Entries/EntriesCollection'; import EntriesSearch from './Entries/EntriesSearch'; import Sidebar from './Sidebar'; import type { ComponentType } from 'react'; import type { ConnectedProps } from 'react-redux'; import type { Collection, TranslatedProps, ViewFilter, ViewGroup } from '../../interface'; import type { RootState } from '../../store'; const CollectionMain = styled('main')` width: 100%; `; const SearchResultContainer = styled('div')` ${components.cardTop}; margin-bottom: 22px; `; const SearchResultHeading = styled('h1')` ${components.cardTopHeading}; `; const CollectionView = ({ collection, collections, collectionName, isSearchEnabled, isSearchResults, isSingleSearchResult, searchTerm, sortableFields, sortByField, sort, viewFilters, viewGroups, filterTerm, t, filterByField, groupByField, filter, group, changeViewStyle, viewStyle, }: TranslatedProps) => { const [readyToLoad, setReadyToLoad] = useState(false); const [prevCollection, setPrevCollection] = useState(); useEffect(() => { setPrevCollection(collection); }, [collection]); const newEntryUrl = useMemo(() => { let url = collection.create ? getNewEntryUrl(collectionName) : ''; if (url && filterTerm) { url = getNewEntryUrl(collectionName); if (filterTerm) { url = `${newEntryUrl}?path=${filterTerm}`; } } return url; }, [collection, collectionName, filterTerm]); const searchResultKey = useMemo( () => `collection.collectionTop.searchResults${isSingleSearchResult ? 'InCollection' : ''}`, [isSingleSearchResult], ); const entries = useMemo(() => { if (isSearchResults) { let searchCollections = collections; if (isSingleSearchResult) { const searchCollection = Object.values(collections).filter(c => c === collection); if (searchCollection.length === 1) { searchCollections = { [searchCollection[0].name]: searchCollection[0], }; } } return ; } return ( ); }, [ collection, collections, filterTerm, isSearchResults, isSingleSearchResult, prevCollection, readyToLoad, searchTerm, viewStyle, ]); const onSortClick = useCallback( async (key: string, direction?: SortDirection) => { await sortByField(collection, key, direction); }, [collection, sortByField], ); const onFilterClick = useCallback( async (filter: ViewFilter) => { await filterByField(collection, filter); }, [collection, filterByField], ); const onGroupClick = useCallback( async (group: ViewGroup) => { await groupByField(collection, group); }, [collection, groupByField], ); useEffect(() => { if (prevCollection === collection) { if (!readyToLoad) { setReadyToLoad(true); } return; } if (sort?.[0]?.key) { if (!readyToLoad) { setReadyToLoad(true); } return; } const defaultSort = collection.sortable_fields.default; if (!defaultSort || !defaultSort.field) { if (!readyToLoad) { setReadyToLoad(true); } return; } setReadyToLoad(false); let alive = true; const sortEntries = () => { setTimeout(async () => { await onSortClick(defaultSort.field, defaultSort.direction ?? SortDirection.Ascending); if (alive) { setReadyToLoad(true); } }); }; sortEntries(); return () => { alive = false; }; }, [collection, onSortClick, prevCollection, readyToLoad, sort]); return ( <> <> {isSearchResults ? ( {t(searchResultKey, { searchTerm, collection: collection.label })} ) : ( <> )} {entries} ); }; interface CollectionViewOwnProps { isSearchResults?: boolean; isSingleSearchResult?: boolean; name: string; searchTerm?: string; filterTerm?: string; } function mapStateToProps(state: RootState, ownProps: TranslatedProps) { const { collections } = state; const isSearchEnabled = state.config.config && state.config.config.search != false; const { isSearchResults, isSingleSearchResult, name, searchTerm = '', filterTerm = '', t, } = ownProps; const collection: Collection = name ? collections[name] : collections[0]; const sort = selectEntriesSort(state.entries, collection.name); const sortableFields = selectSortableFields(collection, t); const viewFilters = selectViewFilters(collection); const viewGroups = selectViewGroups(collection); const filter = selectEntriesFilter(state.entries, collection.name); const group = selectEntriesGroup(state.entries, collection.name); const viewStyle = selectViewStyle(state.entries); return { isSearchResults, isSingleSearchResult, name, searchTerm, filterTerm, collection, collections, collectionName: name, isSearchEnabled, sort, sortableFields, viewFilters, viewGroups, filter, group, viewStyle, }; } const mapDispatchToProps = { sortByField: sortByFieldAction, filterByField: filterByFieldAction, changeViewStyle: changeViewStyleAction, groupByField: groupByFieldAction, }; const connector = connect(mapStateToProps, mapDispatchToProps); export type CollectionViewProps = ConnectedProps; export default translate()(connector(CollectionView)) as ComponentType;