import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { bindActionCreators, compose } from 'redux'; import { capitalize, get, isEmpty, sortBy } from 'lodash'; import { FormattedMessage } from 'react-intl'; import { ButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem, } from 'reactstrap'; import { PluginHeader, PopUpWarning, getQueryParameters, } from 'strapi-helper-plugin'; import pluginId from '../../pluginId'; import { ListViewProvider } from '../../contexts/ListView'; import FilterLogo from '../../assets/images/icon_filter.png'; import Container from '../../components/Container'; import CustomTable from '../../components/CustomTable'; import FilterPicker from '../../components/FilterPicker'; import InputCheckbox from '../../components/InputCheckbox'; import Search from '../../components/Search'; import { generateFiltersFromSearch, generateSearchFromFilters, } from '../../utils/search'; import { onChangeListLabels, resetListLabels } from '../Main/actions'; import { AddFilterCta, DropDownWrapper, Img, Wrapper } from './components'; import Footer from './Footer'; import { getData, onChangeBulk, onChangeBulkSelectall, onDeleteSeveralData, resetProps, toggleModalDeleteAll, } from './actions'; import reducer from './reducer'; import saga from './saga'; import makeSelectListView from './selectors'; function ListView({ count, data, emitEvent, entriesToDelete, location: { search }, getData, layouts, isLoading, history: { push }, match: { params: { slug }, }, onChangeBulk, onChangeBulkSelectall, onChangeListLabels, onDeleteSeveralData, resetListLabels, resetProps, shouldRefetchData, showWarningDeleteAll, toggleModalDeleteAll, }) { strapi.useInjectReducer({ key: 'listView', reducer, pluginId }); strapi.useInjectSaga({ key: 'listView', saga, pluginId }); const getLayoutSettingRef = useRef(); const [isLabelPickerOpen, setLabelPickerState] = useState(false); const [isFilterPickerOpen, setFilterPickerState] = useState(false); getLayoutSettingRef.current = settingName => get(layouts, [slug, 'settings', settingName], ''); const getSearchParams = useCallback( (updatedParams = {}) => { return { _limit: getQueryParameters(search, '_limit') || getLayoutSettingRef.current('pageSize'), _page: getQueryParameters(search, '_page') || 1, _q: getQueryParameters(search, '_q') || '', _sort: getQueryParameters(search, '_sort') || `${getLayoutSettingRef.current( 'defaultSortBy' )}:${getLayoutSettingRef.current('defaultSortOrder')}`, source: getQueryParameters(search, 'source'), ...generateFiltersFromSearch(search), ...updatedParams, }; }, [getLayoutSettingRef, search] ); useEffect(() => { getData(slug, getSearchParams()); return () => { resetProps(); }; /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [slug, shouldRefetchData]); const toggleLabelPickerState = () => setLabelPickerState(prevState => !prevState); const toggleFilterPickerState = () => setFilterPickerState(prevState => !prevState); // Helpers const getMetaDatas = (path = []) => get(layouts, [slug, 'metadata', ...path], {}); const getListLayout = () => get(layouts, [slug, 'layouts', 'list'], []); const getAllLabels = () => { return sortBy( Object.keys(getMetaDatas()) .filter(key => !isEmpty(getMetaDatas([key, 'list']))) .map(label => ({ name: label, value: getListLayout().includes(label), })), ['label', 'name'] ); }; const getFirstSortableElement = (name = '') => { return get( getListLayout().filter(h => { return h !== name && getMetaDatas([h, 'list', 'sortable']) === true; }), ['0'], 'id' ); }; const getTableHeaders = () => { return getListLayout().map(label => { return { ...getMetaDatas([label, 'list']), name: label }; }); }; const handleChangeListLabels = ({ name, value }) => { const currentSort = getSearchParams()._sort; if (value && getListLayout().length === 1) { strapi.notification.error( 'content-manager.notification.error.displayedFields' ); return; } if (currentSort.split(':')[0] === name && value) { emitEvent('didChangeDisplayedFields'); handleChangeParams({ target: { name: '_sort', value: `${getFirstSortableElement(name)}:ASC`, }, }); } onChangeListLabels({ target: { name: `${slug}.${name}`, value: !value }, }); }; const handleChangeParams = ({ target: { name, value } }) => { const updatedSearch = getSearchParams({ [name]: value }); const newSearch = generateSearchFromFilters(updatedSearch); if (name === '_limit') { emitEvent('willChangeNumberOfEntriesPerPage'); } push({ search: newSearch }); resetProps(); getData(slug, updatedSearch); }; const handleSubmit = () => { emitEvent('didFilterEntries'); toggleFilterPickerState(); }; const filterPickerActions = [ { label: `${pluginId}.components.FiltersPickWrapper.PluginHeader.actions.clearAll`, kind: 'secondary', onClick: () => { toggleFilterPickerState(); }, }, { label: `${pluginId}.components.FiltersPickWrapper.PluginHeader.actions.apply`, kind: 'primary', type: 'submit', }, ]; const pluginHeaderActions = [ { id: 'addEntry', label: 'content-manager.containers.List.addAnEntry', labelValues: { entity: capitalize(slug) || 'Content Manager', }, kind: 'primaryAddShape', onClick: () => { emitEvent('willCreateEntry'); }, }, ]; return ( <> {!isFilterPickerOpen && ( 1 ? `${pluginId}.containers.List.pluginHeaderDescription` : `${pluginId}.containers.List.pluginHeaderDescription.singular`, values: { label: count, }, }} title={{ id: slug || 'Content Manager', }} withDescriptionAnim={isLoading} /> )} {getLayoutSettingRef.current('searchable') && ( )}
filter_logo
{msg => ( { resetListLabels(slug); }} >
{msg}
)}
{getAllLabels().map(label => { // return ( handleChangeListLabels(label)} >
handleChangeListLabels(label)} name={label.name} value={label.value} />
); })}
{ onDeleteSeveralData( entriesToDelete, slug, getSearchParams().source ); }} />
); } ListView.defaultProps = { layouts: {}, }; ListView.propTypes = { count: PropTypes.number.isRequired, data: PropTypes.array.isRequired, emitEvent: PropTypes.func.isRequired, entriesToDelete: PropTypes.array.isRequired, layouts: PropTypes.object, location: PropTypes.shape({ search: PropTypes.string.isRequired, }), getData: PropTypes.func.isRequired, isLoading: PropTypes.bool.isRequired, history: PropTypes.shape({ push: PropTypes.func.isRequired, }), match: PropTypes.shape({ params: PropTypes.shape({ slug: PropTypes.string.isRequired, }), }), onChangeBulk: PropTypes.func.isRequired, onChangeBulkSelectall: PropTypes.func.isRequired, onChangeListLabels: PropTypes.func.isRequired, onDeleteSeveralData: PropTypes.func.isRequired, resetListLabels: PropTypes.func.isRequired, resetProps: PropTypes.func.isRequired, shouldRefetchData: PropTypes.bool.isRequired, showWarningDeleteAll: PropTypes.bool.isRequired, toggleModalDeleteAll: PropTypes.func.isRequired, }; const mapStateToProps = makeSelectListView(); export function mapDispatchToProps(dispatch) { return bindActionCreators( { getData, onChangeBulk, onChangeBulkSelectall, onChangeListLabels, onDeleteSeveralData, resetListLabels, resetProps, toggleModalDeleteAll, }, dispatch ); } const withConnect = connect( mapStateToProps, mapDispatchToProps ); export default compose( withConnect, memo )(ListView);