Skip to content

Commit

Permalink
feat: Search Content Tags
Browse files Browse the repository at this point in the history
This change adds the ability to search content tags in the content tags
drawer, in order to filter tags. This change also refactors the way data
is loaded from the server, handling pre-loaded data and pagination.

test: Clean up tests
test: Add more tests to increase coverage
fix: Internationalize checkbox aria-label
refactor: tests nits + debounce lodash swap
fix: fix some type definitions
fix: Fix type issues + increase test cov
test: Update/fix tests
refactor: Remove not needed encoding
feat: Implement pre-loading tags
fix: Spacing of tags in dropdown selector
style: Fix style/spacing inconsistencies
feat: Add tag search in content tags drawer
  • Loading branch information
yusuf-musleh committed Dec 15, 2023
1 parent 94725df commit e989c48
Show file tree
Hide file tree
Showing 25 changed files with 909 additions and 409 deletions.
47 changes: 47 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"@edx/typescript-config": "^1.0.1",
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "12.1.5",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^13.2.1",
"@wojtekmaj/enzyme-adapter-react-17": "0.8.0",
"axios-mock-adapter": "1.22.0",
Expand Down
59 changes: 41 additions & 18 deletions src/content-tags-drawer/ContentTagsCollapsible.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-check
import React from 'react';
import {
Badge,
Expand All @@ -6,10 +7,12 @@ import {
Button,
ModalPopup,
useToggle,
SearchField,
} from '@edx/paragon';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import { debounce } from 'lodash';
import messages from './messages';
import './ContentTagsCollapsible.scss';

Expand All @@ -19,6 +22,9 @@ import ContentTagsTree from './ContentTagsTree';

import useContentTagsCollapsibleHelper from './ContentTagsCollapsibleHelper';

/** @typedef {import("../taxonomy/data/types.mjs").TaxonomyData} TaxonomyData */
/** @typedef {import("./data/types.mjs").Tag} ContentTagData */

/**
* Collapsible component that holds a Taxonomy along with Tags that belong to it.
* This includes both applied tags and tags that are available to select
Expand Down Expand Up @@ -89,22 +95,11 @@ import useContentTagsCollapsibleHelper from './ContentTagsCollapsibleHelper';
* Here is an example of what the value of the "Virology" tag would be:
*
* "Science%20and%20Research,Molecular%2C%20Cellular%2C%20and%20Microbiology,Virology"
* @param {string} contentId - Id of the content object
* @param {Object} taxonomyAndTagsData - Object containing Taxonomy meta data along with applied tags
* @param {number} taxonomyAndTagsData.id - id of Taxonomy
* @param {string} taxonomyAndTagsData.name - name of Taxonomy
* @param {string} taxonomyAndTagsData.description - description of Taxonomy
* @param {boolean} taxonomyAndTagsData.enabled - Whether Taxonomy is enabled/disabled
* @param {boolean} taxonomyAndTagsData.allowMultiple - Whether Taxonomy allows multiple tags to be applied
* @param {boolean} taxonomyAndTagsData.allowFreeText - Whether Taxonomy allows free text tags
* @param {boolean} taxonomyAndTagsData.systemDefined - Whether Taxonomy is system defined or authored by user
* @param {boolean} taxonomyAndTagsData.visibleToAuthors - Whether Taxonomy should be visible to object authors
* @param {string[]} taxonomyAndTagsData.orgs - Array of orgs this Taxonomy belongs to
* @param {boolean} taxonomyAndTagsData.allOrgs - Whether Taxonomy belongs to all orgs
* @param {Object[]} taxonomyAndTagsData.contentTags - Array of taxonomy tags that are applied to the content
* @param {string} taxonomyAndTagsData.contentTags.value - Value of applied Tag
* @param {string} taxonomyAndTagsData.contentTags.lineage - Array of Tag's ancestors sorted (ancestor -> tag)
* @param {boolean} editable - Whether the tags can be edited
*
* @param {Object} props - The component props.
* @param {string} props.contentId - Id of the content object
* @param {TaxonomyData & {contentTags: ContentTagData[]}} props.taxonomyAndTagsData - Taxonomy metadata & applied tags
* @param {boolean} props.editable - Whether the tags can be edited
*/
const ContentTagsCollapsible = ({ contentId, taxonomyAndTagsData, editable }) => {
const intl = useIntl();
Expand All @@ -117,9 +112,30 @@ const ContentTagsCollapsible = ({ contentId, taxonomyAndTagsData, editable }) =>
const [isOpen, open, close] = useToggle(false);
const [addTagsButtonRef, setAddTagsButtonRef] = React.useState(null);

const [searchTerm, setSearchTerm] = React.useState('');

const handleSelectableBoxChange = React.useCallback((e) => {
tagChangeHandler(e.target.value, e.target.checked);
});
}, []);

const handleSearch = debounce((term) => {
setSearchTerm(term.trim());
}, 500); // Perform search after 500ms

const handleSearchChange = React.useCallback((value) => {
if (value === '') {
// No need to debounce when search term cleared
setSearchTerm('');
} else {
handleSearch(value);
}
}, []);

const modalPopupOnCloseHandler = React.useCallback((event) => {
close(event);
// Clear search term
setSearchTerm('');
}, []);

return (
<div className="d-flex">
Expand All @@ -145,7 +161,7 @@ const ContentTagsCollapsible = ({ contentId, taxonomyAndTagsData, editable }) =>
placement="bottom"
positionRef={addTagsButtonRef}
isOpen={isOpen}
onClose={close}
onClose={modalPopupOnCloseHandler}
>
<div className="bg-white p-3 shadow">

Expand All @@ -158,11 +174,18 @@ const ContentTagsCollapsible = ({ contentId, taxonomyAndTagsData, editable }) =>
onChange={handleSelectableBoxChange}
value={checkedTags}
>
<SearchField
onSubmit={() => {}}
onChange={handleSearchChange}
className="mb-2"
/>

<ContentTagsDropDownSelector
key={`selector-${id}`}
taxonomyId={id}
level={0}
tagsTree={tagsTree}
searchTerm={searchTerm}
/>
</SelectableBox.Set>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/content-tags-drawer/ContentTagsCollapsible.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

.taxonomy-tags-selectable-box-set {
grid-auto-rows: unset !important;
grid-gap: unset !important;
overflow-y: scroll;
max-height: 20rem;
}
Expand Down
Loading

0 comments on commit e989c48

Please sign in to comment.