Skip to content

Commit

Permalink
feat: adds filter by tags and contentType to library home
Browse files Browse the repository at this point in the history
Refactor to add search-manager feature.

Co-authored-by:  Yusuf Musleh <[email protected]>
  • Loading branch information
rpenido and yusuf-musleh committed Jul 23, 2024
1 parent 77135cd commit 3d66e47
Show file tree
Hide file tree
Showing 35 changed files with 396 additions and 348 deletions.
3 changes: 2 additions & 1 deletion src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
@import "textbooks/Textbooks";
@import "content-tags-drawer/ContentTagsDropDownSelector";
@import "content-tags-drawer/ContentTagsCollapsible";
@import "search-modal/SearchModal";
@import "search-modal";
@import "search-manager";
@import "certificates/scss/Certificates";
@import "group-configurations/GroupConfigurations";
@import "library-authoring";
Expand Down
6 changes: 2 additions & 4 deletions src/library-authoring/LibraryAuthoringPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import {
screen,
} from '@testing-library/react';
import fetchMock from 'fetch-mock-jest';

import initializeStore from '../store';
import { getContentSearchConfigUrl } from '../search-modal/data/api';
import { getContentSearchConfigUrl } from '../search-manager/data/api';
import mockResult from '../search-modal/__mocks__/search-result.json';
import mockEmptyResult from '../search-modal/__mocks__/empty-search-result.json';
import { getContentLibraryApiUrl, type ContentLibrary } from './data/api';
Expand Down Expand Up @@ -159,8 +158,7 @@ describe('<LibraryAuthoringPage />', () => {
} = render(<RootWrapper />);

// Ensure the search endpoint is called
// One called for LibraryComponents and another called for components count
await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(2, searchEndpoint, 'post'); });
await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });

expect(getByText('Content library')).toBeInTheDocument();
expect(getByText(libraryData.title)).toBeInTheDocument();
Expand Down
119 changes: 64 additions & 55 deletions src/library-authoring/LibraryAuthoringPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ import { StudioFooter } from '@edx/frontend-component-footer';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Button,
Col,
Container,
Icon,
IconButton,
SearchField,
Row,
Tab,
Tabs,
Row,
Col,
} from '@openedx/paragon';
import { Add, InfoOutline } from '@openedx/paragon/icons';
import {
Expand All @@ -21,13 +20,20 @@ import Loading from '../generic/Loading';
import SubHeader from '../generic/sub-header/SubHeader';
import Header from '../header';
import NotFoundAlert from '../generic/NotFoundAlert';
import {
ClearFiltersButton,
FilterByBlockType,
FilterByTags,
SearchContextProvider,
SearchKeywordsField,
} from '../search-manager';
import LibraryComponents from './components/LibraryComponents';
import LibraryCollections from './LibraryCollections';
import LibraryHome from './LibraryHome';
import { useContentLibrary } from './data/apiHooks';
import messages from './messages';
import { LibrarySidebar } from './library-sidebar';
import { LibraryContext } from './common/context';
import messages from './messages';

enum TabList {
home = '',
Expand All @@ -54,7 +60,6 @@ const LibraryAuthoringPage = () => {
const intl = useIntl();
const location = useLocation();
const navigate = useNavigate();
const [searchKeywords, setSearchKeywords] = React.useState('');

const { libraryId } = useParams();

Expand Down Expand Up @@ -87,57 +92,61 @@ const LibraryAuthoringPage = () => {
contextId={libraryId}
isLibrary
/>
<Container size="xl" className="p-4 mt-3">
<SubHeader
title={<SubHeaderTitle title={libraryData.title} />}
subtitle={intl.formatMessage(messages.headingSubtitle)}
headerActions={[
<Button
iconBefore={Add}
variant="primary rounded-0"
onClick={() => openAddContentSidebar()}
disabled={!libraryData.canEditLibrary}
>
{intl.formatMessage(messages.newContentButton)}
</Button>,
]}
/>
<SearchField
value={searchKeywords}
placeholder={intl.formatMessage(messages.searchPlaceholder)}
onChange={(value: string) => setSearchKeywords(value)}
onSubmit={() => {}}
className="w-50"
/>
<Tabs
variant="tabs"
activeKey={activeKey}
onSelect={handleTabChange}
className="my-3"
>
<Tab eventKey={TabList.home} title={intl.formatMessage(messages.homeTab)} />
<Tab eventKey={TabList.components} title={intl.formatMessage(messages.componentsTab)} />
<Tab eventKey={TabList.collections} title={intl.formatMessage(messages.collectionsTab)} />
</Tabs>
<Routes>
<Route
path={TabList.home}
element={<LibraryHome libraryId={libraryId} filter={{ searchKeywords }} />}
/>
<Route
path={TabList.components}
element={<LibraryComponents libraryId={libraryId} filter={{ searchKeywords }} variant="full" />}
/>
<Route
path={TabList.collections}
element={<LibraryCollections />}
/>
<Route
path="*"
element={<NotFoundAlert />}
<SearchContextProvider
extraFilter={`context_key = "${libraryId}"`}
>
<Container size="xl" className="p-4 mt-3">
<SubHeader
title={<SubHeaderTitle title={libraryData.title} />}
subtitle={intl.formatMessage(messages.headingSubtitle)}
headerActions={[
<Button
iconBefore={Add}
variant="primary rounded-0"
onClick={openAddContentSidebar}
disabled={!libraryData.canEditLibrary}
>
{intl.formatMessage(messages.newContentButton)}
</Button>,
]}
/>
</Routes>
</Container>
<SearchKeywordsField className="w-50" />
<div className="d-flex mt-3 align-items-center">
<FilterByTags />
<FilterByBlockType />
<ClearFiltersButton />
<div className="flex-grow-1" />
</div>
<Tabs
variant="tabs"
activeKey={activeKey}
onSelect={handleTabChange}
className="my-3"
>
<Tab eventKey={TabList.home} title={intl.formatMessage(messages.homeTab)} />
<Tab eventKey={TabList.components} title={intl.formatMessage(messages.componentsTab)} />
<Tab eventKey={TabList.collections} title={intl.formatMessage(messages.collectionsTab)} />
</Tabs>
<Routes>
<Route
path={TabList.home}
element={<LibraryHome libraryId={libraryId} />}
/>
<Route
path={TabList.components}
element={<LibraryComponents libraryId={libraryId} variant="full" />}
/>
<Route
path={TabList.collections}
element={<LibraryCollections />}
/>
<Route
path="*"
element={<NotFoundAlert />}
/>
</Routes>
</Container>
</SearchContextProvider>
<StudioFooter />
</Col>
{ sidebarBodyComponent !== null && (
Expand Down
20 changes: 11 additions & 9 deletions src/library-authoring/LibraryHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import {
Card, Stack,
} from '@openedx/paragon';

import { useSearchContext } from '../search-manager';
import { NoComponents, NoSearchResults } from './EmptyStates';
import LibraryCollections from './LibraryCollections';
import { useLibraryComponentCount } from './data/apiHooks';
import messages from './messages';
import { LibraryComponents } from './components';
import messages from './messages';

const Section = ({ title, children } : { title: string, children: React.ReactNode }) => (
<Card>
Expand All @@ -23,15 +23,17 @@ const Section = ({ title, children } : { title: string, children: React.ReactNod

type LibraryHomeProps = {
libraryId: string,
filter: {
searchKeywords: string,
},
};

const LibraryHome = ({ libraryId, filter } : LibraryHomeProps) => {
const LibraryHome = ({ libraryId } : LibraryHomeProps) => {
const intl = useIntl();
const { searchKeywords } = filter;
const { componentCount, collectionCount } = useLibraryComponentCount(libraryId, searchKeywords);

const {
totalHits: componentCount,
searchKeywords,
} = useSearchContext();

const collectionCount = 0;

if (componentCount === 0) {
return searchKeywords === '' ? <NoComponents /> : <NoSearchResults />;
Expand All @@ -46,7 +48,7 @@ const LibraryHome = ({ libraryId, filter } : LibraryHomeProps) => {
<LibraryCollections />
</Section>
<Section title={`Components (${componentCount})`}>
<LibraryComponents libraryId={libraryId} filter={filter} variant="preview" />
<LibraryComponents libraryId={libraryId} variant="preview" />
</Section>
</Stack>
);
Expand Down
8 changes: 4 additions & 4 deletions src/library-authoring/components/ComponentCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import {
} from '@openedx/paragon';
import { MoreVert } from '@openedx/paragon/icons';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import messages from './messages';
import TagCount from '../../generic/tag-count';

import { getItemIcon, getComponentStyleColor } from '../../generic/block-type-utils';
import { ContentHit } from '../../search-modal/data/api';
import Highlight from '../../search-modal/Highlight';
import TagCount from '../../generic/tag-count';
import { type ContentHit, Highlight } from '../../search-manager';
import messages from './messages';

type ComponentCardProps = {
contentHit: ContentHit,
Expand Down
Loading

0 comments on commit 3d66e47

Please sign in to comment.