refactor: Separate Publish order sort from publish filter [FC-0076] (#1701)

This commit is contained in:
Chris Chávez
2025-03-10 10:55:15 -05:00
committed by GitHub
parent 17ebb90cd1
commit b2472cfc0a
4 changed files with 23 additions and 36 deletions

View File

@@ -311,8 +311,13 @@ describe('<LibraryAuthoringPage />', () => {
expect(options.length).toBeGreaterThan(0);
fireEvent.click(options[options.length - 1]);
let bodyText;
// Did the search happen with the expected sort option?
const bodyText = sortBy ? `"sort":["${sortBy}"]` : '"sort":[]';
if (Array.isArray(sortBy)) {
bodyText = `"sort":[${sortBy.map(item => `"${item}"`).join(',')}]`;
} else {
bodyText = sortBy ? `"sort":["${sortBy}"]` : '"sort":[]';
}
await waitFor(() => {
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
body: expect.stringContaining(bodyText),
@@ -336,15 +341,8 @@ describe('<LibraryAuthoringPage />', () => {
await testSortOption('Newest', 'created:desc', false);
await testSortOption('Oldest', 'created:asc', false);
// Sorting by Recently Published also excludes unpublished components
await testSortOption('Recently Published', 'last_published:desc', false);
await waitFor(() => {
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
body: expect.stringContaining('last_published IS NOT NULL'),
method: 'POST',
headers: expect.anything(),
});
});
// Sorting by Recently Published also sorts unpublished components by recently modified
await testSortOption('Recently Published', ['last_published:desc', 'modified:desc'], false);
// Re-selecting the previous sort option resets sort to default "Recently Modified"
await testSortOption('Recently Published', 'modified:desc', true);

View File

@@ -268,8 +268,13 @@ describe('<LibraryCollectionPage />', () => {
expect(options.length).toBeGreaterThan(0);
fireEvent.click(options[options.length - 1]);
let bodyText;
// Did the search happen with the expected sort option?
const bodyText = sortBy ? `"sort":["${sortBy}"]` : '"sort":[]';
if (Array.isArray(sortBy)) {
bodyText = `"sort":[${sortBy.map(item => `"${item}"`).join(',')}]`;
} else {
bodyText = sortBy ? `"sort":["${sortBy}"]` : '"sort":[]';
}
await waitFor(() => {
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
body: expect.stringContaining(bodyText),
@@ -293,15 +298,8 @@ describe('<LibraryCollectionPage />', () => {
await testSortOption('Newest', 'created:desc', false);
await testSortOption('Oldest', 'created:asc', false);
// Sorting by Recently Published also excludes unpublished components
await testSortOption('Recently Published', 'last_published:desc', false);
await waitFor(() => {
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
body: expect.stringContaining('last_published IS NOT NULL'),
method: 'POST',
headers: expect.anything(),
});
});
// Sorting by Recently Published also sorts unpublished components by recently modified
await testSortOption('Recently Published', ['last_published:desc', 'modified:desc'], false);
// Re-selecting the previous sort option resets sort to default "Recently Modified"
await testSortOption('Recently Published', 'modified:desc', true);

View File

@@ -10,34 +10,23 @@ import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
import SearchFilterWidget from './SearchFilterWidget';
import { useSearchContext } from './SearchManager';
import { PublishStatus, SearchSortOption } from './data/api';
import { PublishStatus } from './data/api';
/**
* A button with a dropdown that allows filtering the current search by publish status
*/
const FilterByPublished: React.FC<Record<never, never>> = () => {
const [onlyPublished, setOnlyPublished] = React.useState(false);
const intl = useIntl();
const {
publishStatus,
publishStatusFilter,
setPublishStatusFilter,
searchSortOrder,
} = useSearchContext();
const clearFilters = React.useCallback(() => {
setPublishStatusFilter([]);
}, []);
React.useEffect(() => {
if (searchSortOrder === SearchSortOption.RECENTLY_PUBLISHED) {
setPublishStatusFilter([PublishStatus.Published, PublishStatus.Modified]);
setOnlyPublished(true);
} else {
setOnlyPublished(false);
}
}, [searchSortOrder]);
const toggleFilterMode = React.useCallback((mode: PublishStatus) => {
setPublishStatusFilter(oldList => {
if (oldList.includes(mode)) {
@@ -90,7 +79,6 @@ const FilterByPublished: React.FC<Record<never, never>> = () => {
as={Form.Checkbox}
value={PublishStatus.NeverPublished}
onChange={() => { toggleFilterMode(PublishStatus.NeverPublished); }}
disabled={onlyPublished}
>
<div>
{intl.formatMessage(messages.publishStatusNeverPublished)}

View File

@@ -149,10 +149,13 @@ export const SearchContextProvider: React.FC<{
// SearchSortOption.RELEVANCE is special, it means "no custom sorting", so we
// send it to useContentSearchResults as an empty array.
const searchSortOrderToUse = overrideSearchSortOrder ?? searchSortOrder;
const sort: SearchSortOption[] = (searchSortOrderToUse === SearchSortOption.RELEVANCE ? [] : [searchSortOrderToUse]);
// Selecting SearchSortOption.RECENTLY_PUBLISHED also excludes unpublished components.
let sort: SearchSortOption[] = (searchSortOrderToUse === SearchSortOption.RELEVANCE ? [] : [searchSortOrderToUse]);
// Adding `SearchSortOption.RECENTLY_MODIFIED` as second sort when
// selecting `SearchSortOption.RECENTLY_PUBLISHED`.
// This is to sort the never published components by recently modified that
// appears in the end after all published components.
if (searchSortOrderToUse === SearchSortOption.RECENTLY_PUBLISHED) {
extraFilter = union(extraFilter, ['last_published IS NOT NULL']);
sort = union(sort, [SearchSortOption.RECENTLY_MODIFIED]);
}
const canClearFilters = (