diff --git a/src/index.scss b/src/index.scss index bc0a403f1b..f1e1999361 100755 --- a/src/index.scss +++ b/src/index.scss @@ -19,3 +19,4 @@ @import "course-updates/CourseUpdates"; @import "export-page/CourseExportPage"; @import "import-page/CourseImportPage"; +@import "taxonomy/TaxonomyCard.scss"; diff --git a/src/taxonomy/TaxonomyCard.jsx b/src/taxonomy/TaxonomyCard.jsx index 53ac777c52..c4d4c25d5a 100644 --- a/src/taxonomy/TaxonomyCard.jsx +++ b/src/taxonomy/TaxonomyCard.jsx @@ -1,21 +1,29 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Badge, + IconButton, Card, OverlayTrigger, Popover, + ModalPopup, + Menu, + Icon, + MenuItem, } from '@edx/paragon'; +import { MoreVert } from '@edx/paragon/icons'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import messages from './messages'; -import './TaxonomyCard.scss'; const TaxonomyCard = ({ className, original, intl }) => { const { id, name, description, systemDefined, orgsCount, } = original; + const [menuIsOpen, setMenuIsOpen] = useState(false); + const [menuTarget, setMenuTarget] = useState(null); + const orgsCountEnabled = () => orgsCount !== undefined && orgsCount !== 0; const getSystemBadgeToolTip = () => ( @@ -53,10 +61,33 @@ const TaxonomyCard = ({ className, original, intl }) => { return undefined; }; + const onClickExport = () => { + setMenuIsOpen(false); + }; + const getHeaderActions = () => ( - // Menu button - // TODO Add functionality to this menu - undefined + <> + setMenuIsOpen(true)} + ref={setMenuTarget} + src={MoreVert} + iconAs={Icon} + alt={intl.formatMessage(messages.taxonomyMenuAlt, { name })} + data-testid={`taxonomy-card-menu-button-${id}`} + /> + setMenuIsOpen(false)} + > + + + {intl.formatMessage(messages.taxonomyCardExportMenu)} + + + + ); return ( diff --git a/src/taxonomy/TaxonomyCard.scss b/src/taxonomy/TaxonomyCard.scss index 35e198abe8..b4839bd1c2 100644 --- a/src/taxonomy/TaxonomyCard.scss +++ b/src/taxonomy/TaxonomyCard.scss @@ -29,4 +29,21 @@ text-overflow: ellipsis; white-space: nowrap; } + + .taxonomy-menu-item:focus { + /** + * There is a bug in the menu that auto focus the first item. + * We convert the focus style to a normal style. + */ + background-color: white !important; + font-weight: normal !important; + } + + .taxonomy-menu-item:focus:hover { + /** + * Check the previous block about the focus. + * This enable a normal hover to focused items. + */ + background-color: $light-500 !important; + } } diff --git a/src/taxonomy/TaxonomyCard.test.jsx b/src/taxonomy/TaxonomyCard.test.jsx index d4efe90bc1..a4e192342a 100644 --- a/src/taxonomy/TaxonomyCard.test.jsx +++ b/src/taxonomy/TaxonomyCard.test.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n'; import { initializeMockApp } from '@edx/frontend-platform'; import { AppProvider } from '@edx/frontend-platform/react'; -import { render } from '@testing-library/react'; +import { render, fireEvent } from '@testing-library/react'; import PropTypes from 'prop-types'; import initializeStore from '../store'; @@ -12,6 +12,7 @@ import TaxonomyCard from './TaxonomyCard'; let store; const data = { + id: 1, name: 'Taxonomy 1', description: 'This is a description', }; @@ -81,4 +82,23 @@ describe('', async () => { const { getByText } = render(); expect(getByText('Assigned to 6 orgs')).toBeInTheDocument(); }); + + test('should open and close menu on button click', () => { + const { getByTestId, getByText } = render(); + + // Menu closed + expect(() => getByTestId('taxonomy-card-menu-1')).toThrow(); + + // Click on the menu button to open + fireEvent.click(getByTestId('taxonomy-card-menu-button-1')); + + // Menu open + expect(getByTestId('taxonomy-card-menu-1')).toBeInTheDocument(); + + // Click on any element to close the menu + fireEvent.click(getByText('Export')); + + // Menu closed + expect(() => getByTestId('taxonomy-card-menu-1')).toThrow(); + }); }); diff --git a/src/taxonomy/messages.js b/src/taxonomy/messages.js index c92cdc788f..f64a56156c 100644 --- a/src/taxonomy/messages.js +++ b/src/taxonomy/messages.js @@ -37,6 +37,14 @@ const messages = defineMessages({ id: 'course-authoring.taxonomy-list.popover.system-defined.body', defaultMessage: 'This is a system-level taxonomy and is enabled by default.', }, + taxonomyCardExportMenu: { + id: 'course-authoring.taxonomy-list.menu.export.label', + defaultMessage: 'Export', + }, + taxonomyMenuAlt: { + id: 'course-authoring.taxonomy-list.menu.alt', + defaultMessage: '{name} menu', + }, }); export default messages;