diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/ListView/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/ListView/index.js index a51b7e35ee..803c8d8b0f 100644 --- a/packages/strapi-plugin-content-manager/admin/src/containers/ListView/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/ListView/index.js @@ -1,4 +1,4 @@ -import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; +import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { bindActionCreators, compose } from 'redux'; @@ -74,7 +74,9 @@ function ListView({ const [isLabelPickerOpen, setLabelPickerState] = useState(false); const [isFilterPickerOpen, setFilterPickerState] = useState(false); const [idToDelete, setIdToDelete] = useState(null); - const contentTypePath = [slug, 'contentType']; + const contentTypePath = useMemo(() => { + return [slug, 'contentType']; + }, [slug]); getDataRef.current = async (uid, params) => { try { @@ -94,8 +96,51 @@ function ListView({ } }; - getLayoutSettingRef.current = settingName => - get(layouts, [...contentTypePath, 'settings', settingName], ''); + getLayoutSettingRef.current = settingName => { + return get(layouts, [...contentTypePath, 'settings', settingName], ''); + }; + + const getMetaDatas = useCallback( + (path = []) => { + return get(layouts, [...contentTypePath, 'metadatas', ...path], {}); + }, + [contentTypePath, layouts] + ); + + const listLayout = useMemo(() => { + return get(layouts, [...contentTypePath, 'layouts', 'list'], []); + }, [contentTypePath, layouts]); + + const listSchema = useMemo(() => { + return get(layouts, [...contentTypePath, 'schema'], {}); + }, [layouts, contentTypePath]); + + const label = useMemo(() => { + return get(listSchema, ['info', 'name'], ''); + }, [listSchema]); + + const tableHeaders = useMemo(() => { + return listLayout.map(label => { + return { ...getMetaDatas([label, 'list']), name: label }; + }); + }, [getMetaDatas, listLayout]); + + const searchValue = useMemo(() => { + return getQueryParameters(search, '_q') || ''; + }, [search]); + + const getFirstSortableElement = useCallback( + (name = '') => { + return get( + listLayout.filter(h => { + return h !== name && getMetaDatas([h, 'list', 'sortable']) === true; + }), + ['0'], + 'id' + ); + }, + [getMetaDatas, listLayout] + ); const getSearchParams = useCallback( (updatedParams = {}) => { @@ -148,6 +193,23 @@ function ListView({ } }, [entriesToDelete, onDeleteSeveralDataSucceeded, slug]); + const allLabels = useMemo(() => { + return sortBy( + Object.keys(getMetaDatas()) + .filter( + key => + !['json', 'component', 'dynamiczone', 'relation', 'richtext'].includes( + get(listSchema, ['attributes', key, 'type'], '') + ) + ) + .map(label => ({ + name: label, + value: listLayout.includes(label), + })), + ['label', 'name'] + ); + }, [getMetaDatas, listLayout, listSchema]); + useEffect(() => { getDataRef.current(slug, getSearchParams()); @@ -165,6 +227,7 @@ function ListView({ setLabelPickerState(prevState => !prevState); }; + const toggleFilterPickerState = () => { if (!isFilterPickerOpen) { emitEvent('willFilterEntries'); @@ -173,52 +236,10 @@ function ListView({ setFilterPickerState(prevState => !prevState); }; - // Helpers - const getMetaDatas = (path = []) => get(layouts, [...contentTypePath, 'metadatas', ...path], {}); - - const getListLayout = () => get(layouts, [...contentTypePath, 'layouts', 'list'], []); - - const getListSchema = () => get(layouts, [...contentTypePath, 'schema'], {}); - - const getName = () => { - return get(getListSchema(), ['info', 'name'], ''); - }; - - const getAllLabels = () => { - return sortBy( - Object.keys(getMetaDatas()) - .filter( - key => - !['json', 'component', 'dynamiczone', 'relation', 'richtext'].includes( - get(getListSchema(), ['attributes', key, 'type'], '') - ) - ) - .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) { + if (value && listLayout.length === 1) { strapi.notification.error('content-manager.notification.error.displayedFields'); return; @@ -255,10 +276,12 @@ function ListView({ resetProps(); getDataRef.current(slug, updatedSearch); }; + const handleClickDelete = id => { setIdToDelete(id); toggleModalDelete(); }; + const handleSubmit = (filters = []) => { emitEvent('didFilterEntries'); toggleFilterPickerState(); @@ -281,49 +304,56 @@ function ListView({ }, ]; - const headerAction = [ - { - label: formatMessage( - { - id: 'content-manager.containers.List.addAnEntry', - }, - { - entity: getName() || 'Content Manager', - } - ), - onClick: () => { - emitEvent('willCreateEntry'); - push({ - pathname: `${pathname}/create`, - search: `redirectUrl=${pathname}${search}`, - }); - }, - color: 'primary', - type: 'button', - icon: true, - style: { - paddingLeft: 15, - paddingRight: 15, - fontWeight: 600, - }, - }, - ]; - - const headerProps = { - title: { - label: getName() || 'Content Manager', - }, - content: formatMessage( + const headerAction = useMemo( + () => [ { - id: - count > 1 - ? `${pluginId}.containers.List.pluginHeaderDescription` - : `${pluginId}.containers.List.pluginHeaderDescription.singular`, + label: formatMessage( + { + id: 'content-manager.containers.List.addAnEntry', + }, + { + entity: label || 'Content Manager', + } + ), + onClick: () => { + emitEvent('willCreateEntry'); + push({ + pathname: `${pathname}/create`, + search: `redirectUrl=${pathname}${search}`, + }); + }, + color: 'primary', + type: 'button', + icon: true, + style: { + paddingLeft: 15, + paddingRight: 15, + fontWeight: 600, + }, }, - { label: count } - ), - actions: headerAction, - }; + ], + // eslint-disable-next-line react-hooks/exhaustive-deps + [label, pathname, search] + ); + + const headerProps = useMemo(() => { + return { + title: { + label: label || 'Content Manager', + }, + content: formatMessage( + { + id: + count > 1 + ? `${pluginId}.containers.List.pluginHeaderDescription` + : `${pluginId}.containers.List.pluginHeaderDescription.singular`, + }, + { label: count } + ), + actions: headerAction, + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [count, headerAction, label]); return ( <> @@ -333,12 +363,12 @@ function ListView({ entriesToDelete={entriesToDelete} emitEvent={emitEvent} firstSortableElement={getFirstSortableElement()} - label={getName()} + label={label} onChangeBulk={onChangeBulk} onChangeBulkSelectall={onChangeBulkSelectall} onChangeParams={handleChangeParams} onClickDelete={handleClickDelete} - schema={getListSchema()} + schema={listSchema} searchParams={getSearchParams()} slug={slug} toggleModalDeleteAll={toggleModalDeleteAll} @@ -346,7 +376,7 @@ function ListView({ @@ -355,9 +385,9 @@ function ListView({ {getLayoutSettingRef.current('searchable') && ( )} @@ -376,7 +406,7 @@ function ListView({ changeParams={handleChangeParams} filters={getSearchParams().filters} index={key} - schema={getListSchema()} + schema={listSchema} key={key} toggleFilterPickerState={toggleFilterPickerState} isFilterPickerOpen={isFilterPickerOpen} @@ -390,7 +420,7 @@ function ListView({ { resetListLabels(slug); @@ -405,7 +435,7 @@ function ListView({