diff --git a/packages/core/admin/admin/src/content-manager/components/AttributeFilter/AdminUsersFilter.js b/packages/core/admin/admin/src/content-manager/components/AttributeFilter/AdminUsersFilter.js new file mode 100644 index 0000000000..674e803955 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/AttributeFilter/AdminUsersFilter.js @@ -0,0 +1,39 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Combobox, ComboboxOption } from '@strapi/design-system'; +import { getDisplayName } from '@strapi/helper-plugin'; +import { useIntl } from 'react-intl'; + +import { useAdminUsers } from '../../../hooks/useAdminUsers'; + +const AdminUsersFilter = ({ value, onChange }) => { + const { formatMessage } = useIntl(); + const { users, isLoading } = useAdminUsers({}, { staleTime: 2 * (1000 * 60) }); + const ariaLabel = formatMessage({ + id: 'content-manager.components.Filters.usersSelect.label', + defaultMessage: 'Search and select an user to filter', + }); + + return ( + + {users.map((user) => { + return ( + + {getDisplayName(user, formatMessage)} + + ); + })} + + ); +}; + +AdminUsersFilter.propTypes = { + onChange: PropTypes.func.isRequired, + value: PropTypes.string, +}; + +AdminUsersFilter.defaultProps = { + value: '', +}; + +export { AdminUsersFilter }; \ No newline at end of file diff --git a/packages/core/admin/admin/src/content-manager/components/AttributeFilter/index.js b/packages/core/admin/admin/src/content-manager/components/AttributeFilter/index.js index b34e5a1d33..78a2291d71 100644 --- a/packages/core/admin/admin/src/content-manager/components/AttributeFilter/index.js +++ b/packages/core/admin/admin/src/content-manager/components/AttributeFilter/index.js @@ -2,14 +2,77 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; - -import Filters from './Filters'; +import { useQueryParams } from '@strapi/helper-plugin'; +import { useAdminUsers } from '../../../hooks/useAdminUsers'; import useAllowedAttributes from './hooks/useAllowedAttributes'; +import Filters from './Filters'; +import { AdminUsersFilter } from './AdminUsersFilter'; + +const AUTHOR_ATTRIBUTES = ['createdBy', 'updatedBy']; const AttributeFilter = ({ contentType, slug, metadatas }) => { const { formatMessage } = useIntl(); + + const [{ query }] = useQueryParams(); + // We get the users selected' ids + const selectedUsers = + query?.filters?.$and?.reduce((acc, filter) => { + const [key, value] = Object.entries(filter)[0]; + const id = value.id?.$eq || value.id?.$ne; + + if (AUTHOR_ATTRIBUTES.includes(key) && !acc.includes(id)) { + acc.push(id); + } + + return acc; + }, []) ?? []; + const { users, isLoading } = useAdminUsers( + { filter: { id: { in: selectedUsers } } }, + { + enabled: selectedUsers.length > 0, + } + ); + const allowedAttributes = useAllowedAttributes(contentType, slug); const displayedFilters = allowedAttributes.map((name) => { + if (AUTHOR_ATTRIBUTES.includes(name)) { + return { + name, + metadatas: { + label: formatMessage({ + id: `content-manager.components.Filters.${name}`, + defaultMessage: name, + }), + customOperators: [ + { + intlLabel: { id: 'components.FilterOptions.FILTER_TYPES.$eq', defaultMessage: 'is' }, + value: '$eq', + }, + { + intlLabel: { + id: 'components.FilterOptions.FILTER_TYPES.$ne', + defaultMessage: 'is not', + }, + value: '$ne', + }, + ], + customInput: AdminUsersFilter, + options: users.map((user) => ({ + label: user.firstname, + customValue: user.id.toString(), + })), + }, + fieldSchema: { + type: 'relation', + mainField: { name: 'id' }, + trackedEvent: { + name: 'didFilterEntries', + properties: { useRelation: true }, + }, + }, + }; + } + const attribute = contentType.attributes[name]; const { type, enum: options } = attribute; @@ -28,6 +91,10 @@ const AttributeFilter = ({ contentType, slug, metadatas }) => { }; }); + if (isLoading) { + return null; + } + return ; };