diff --git a/README.rst b/README.rst
index bc7c97066..8959458aa 100644
--- a/README.rst
+++ b/README.rst
@@ -250,6 +250,25 @@ Requirements
* ``contentstore.new_studio_mfe.use_new_export_page``: this feature flag will change the CMS to link to the new export page.
* ``contentstore.new_studio_mfe.use_new_import_page``: this feature flag will change the CMS to link to the new import page.
+Feature: Tagging/Taxonomy Pages
+================================
+
+.. image:: ./docs/readme-images/feature-tagging-taxonomy-pages.png
+
+Requirements
+------------
+
+* ``edx-platform`` Waffle flags:
+
+ * ``contentstore.new_studio_mfe.use_tagging_taxonomy_list_page``: this feature flag must be enabled.
+
+Configuration
+-------------
+
+In additional to the standard settings, the following local configuration items are required:
+
+* ``ENABLE_TAGGING_TAXONOMY_PAGES``: must be enabled in order to actually present the new Tagging/Taxonomy pages.
+
Developing
**********
diff --git a/docs/readme-images/feature-tagging-taxonomy-pages.png b/docs/readme-images/feature-tagging-taxonomy-pages.png
new file mode 100644
index 000000000..e27c469c5
Binary files /dev/null and b/docs/readme-images/feature-tagging-taxonomy-pages.png differ
diff --git a/src/index.scss b/src/index.scss
index 3fed92570..2146be3a4 100755
--- a/src/index.scss
+++ b/src/index.scss
@@ -18,4 +18,5 @@
@import "course-updates/CourseUpdates";
@import "export-page/CourseExportPage";
@import "import-page/CourseImportPage";
+@import "taxonomy/taxonomy-card/TaxonomyCard";
@import "files-and-videos";
diff --git a/src/taxonomy/TaxonomyCard.jsx b/src/taxonomy/TaxonomyCard.jsx
deleted file mode 100644
index 203782365..000000000
--- a/src/taxonomy/TaxonomyCard.jsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import React from 'react';
-import {
- Badge,
- Card,
-} from '@edx/paragon';
-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 orgsCountEnabled = () => orgsCount !== undefined && orgsCount !== 0;
-
- const getHeaderSubtitle = () => {
- if (systemDefined) {
- return (
-
- {intl.formatMessage(messages.systemDefinedBadge)}
-
- );
- }
- if (orgsCountEnabled()) {
- return (
-
- {intl.formatMessage(messages.assignedToOrgsLabel, { orgsCount })}
-
- );
- }
- return undefined;
- };
-
- const getHeaderActions = () => (
- // Menu button
- // TODO Add functionality to this menu
- undefined
- );
-
- return (
-
-
-
-
- {description}
-
-
-
- );
-};
-
-TaxonomyCard.defaultProps = {
- className: '',
-};
-
-TaxonomyCard.propTypes = {
- className: PropTypes.string,
- original: PropTypes.shape({
- id: PropTypes.number,
- name: PropTypes.string,
- description: PropTypes.string,
- systemDefined: PropTypes.bool,
- orgsCount: PropTypes.number,
- }).isRequired,
- intl: intlShape.isRequired,
-};
-
-export default injectIntl(TaxonomyCard);
diff --git a/src/taxonomy/TaxonomyListPage.jsx b/src/taxonomy/TaxonomyListPage.jsx
index 5d73ef664..98e446e45 100644
--- a/src/taxonomy/TaxonomyListPage.jsx
+++ b/src/taxonomy/TaxonomyListPage.jsx
@@ -5,15 +5,16 @@ import {
DataTable,
Spinner,
} from '@edx/paragon';
-import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { StudioFooter } from '@edx/frontend-component-footer';
+import { useIntl } from '@edx/frontend-platform/i18n';
import Header from '../header';
import SubHeader from '../generic/sub-header/SubHeader';
import messages from './messages';
-import TaxonomyCard from './TaxonomyCard';
-import { useTaxonomyListDataResponse, useIsTaxonomyListDataLoaded } from './api/hooks/selectors';
+import TaxonomyCard from './taxonomy-card';
+import { useTaxonomyListDataResponse, useIsTaxonomyListDataLoaded } from './data/apiHooks';
-const TaxonomyListPage = ({ intl }) => {
+const TaxonomyListPage = () => {
+ const intl = useIntl();
const useTaxonomyListData = () => {
const taxonomyListData = useTaxonomyListDataResponse();
const isLoaded = useIsTaxonomyListDataLoaded();
@@ -97,8 +98,6 @@ const TaxonomyListPage = ({ intl }) => {
);
};
-TaxonomyListPage.propTypes = {
- intl: intlShape.isRequired,
-};
+TaxonomyListPage.propTypes = {};
-export default injectIntl(TaxonomyListPage);
+export default TaxonomyListPage;
diff --git a/src/taxonomy/TaxonomyListPage.test.jsx b/src/taxonomy/TaxonomyListPage.test.jsx
index 99c947b75..8e6834756 100644
--- a/src/taxonomy/TaxonomyListPage.test.jsx
+++ b/src/taxonomy/TaxonomyListPage.test.jsx
@@ -7,11 +7,11 @@ import { act, render } from '@testing-library/react';
import initializeStore from '../store';
import TaxonomyListPage from './TaxonomyListPage';
-import { useTaxonomyListDataResponse, useIsTaxonomyListDataLoaded } from './api/hooks/selectors';
+import { useTaxonomyListDataResponse, useIsTaxonomyListDataLoaded } from './data/apiHooks';
let store;
-jest.mock('./api/hooks/selectors', () => ({
+jest.mock('./data/apiHooks', () => ({
useTaxonomyListDataResponse: jest.fn(),
useIsTaxonomyListDataLoaded: jest.fn(),
}));
diff --git a/src/taxonomy/__mocks__/index.js b/src/taxonomy/__mocks__/index.js
new file mode 100644
index 000000000..bbbeb62a2
--- /dev/null
+++ b/src/taxonomy/__mocks__/index.js
@@ -0,0 +1,2 @@
+// eslint-disable-next-line import/prefer-default-export
+export { default as taxonomyListMock } from './taxonomyListMock';
diff --git a/src/taxonomy/__mocks__/taxonomyListMock.js b/src/taxonomy/__mocks__/taxonomyListMock.js
new file mode 100644
index 000000000..5eab0af02
--- /dev/null
+++ b/src/taxonomy/__mocks__/taxonomyListMock.js
@@ -0,0 +1,50 @@
+module.exports = {
+ next: null,
+ previous: null,
+ count: 4,
+ numPages: 1,
+ currentPage: 1,
+ start: 0,
+ results: [
+ {
+ id: -2,
+ name: 'Content Authors',
+ description: 'Allows tags for any user ID created on the instance.',
+ enabled: true,
+ allowMultiple: false,
+ allowFreeText: false,
+ systemDefined: true,
+ visibleToAuthors: false,
+ },
+ {
+ id: -1,
+ name: 'Languages',
+ description: 'lang lang lang lang lang lang lang lang',
+ enabled: true,
+ allowMultiple: false,
+ allowFreeText: false,
+ systemDefined: true,
+ visibleToAuthors: true,
+ },
+ {
+ id: 1,
+ name: 'Taxonomy',
+ description: 'This is a Description',
+ enabled: true,
+ allowMultiple: false,
+ allowFreeText: false,
+ systemDefined: false,
+ visibleToAuthors: true,
+ },
+ {
+ id: 2,
+ name: 'Taxonomy long long long long long long long long long long long long long long long long long long long',
+ description: 'This is a Description long lon',
+ enabled: true,
+ allowMultiple: false,
+ allowFreeText: false,
+ systemDefined: false,
+ visibleToAuthors: true,
+ },
+ ],
+};
diff --git a/src/taxonomy/api/hooks/api.js b/src/taxonomy/api/hooks/api.js
deleted file mode 100644
index 6da57c171..000000000
--- a/src/taxonomy/api/hooks/api.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// @ts-check
-import { useQuery } from '@tanstack/react-query';
-import { camelCaseObject, getConfig } from '@edx/frontend-platform';
-import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
-
-const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
-const getTaxonomyListApiUrl = new URL('api/content_tagging/v1/taxonomies/?enabled=true', getApiBaseUrl()).href;
-
-/**
- * @returns {import("../types.mjs").UseQueryResult}
- */
-const useTaxonomyListData = () => (
- useQuery({
- queryKey: ['taxonomyList'],
- queryFn: () => getAuthenticatedHttpClient().get(getTaxonomyListApiUrl)
- .then(camelCaseObject),
- })
-);
-
-export default useTaxonomyListData;
diff --git a/src/taxonomy/api/hooks/api.test.js b/src/taxonomy/api/hooks/api.test.js
deleted file mode 100644
index aee14b8a7..000000000
--- a/src/taxonomy/api/hooks/api.test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useQuery } from '@tanstack/react-query';
-import useTaxonomyListData from './api';
-
-jest.mock('@tanstack/react-query', () => ({
- useQuery: jest.fn(),
-}));
-
-jest.mock('@edx/frontend-platform/auth', () => ({
- getAuthenticatedHttpClient: jest.fn(),
-}));
-
-describe('taxonomy API: useTaxonomyListData', () => {
- afterEach(() => {
- jest.clearAllMocks();
- });
-
- it('should call useQuery with the correct parameters', () => {
- useTaxonomyListData();
-
- expect(useQuery).toHaveBeenCalledWith({
- queryKey: ['taxonomyList'],
- queryFn: expect.any(Function),
- });
- });
-});
diff --git a/src/taxonomy/api/hooks/selectors.js b/src/taxonomy/api/hooks/selectors.js
deleted file mode 100644
index 6908827ca..000000000
--- a/src/taxonomy/api/hooks/selectors.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// @ts-check
-import useTaxonomyListData from './api';
-
-/**
- * @returns {import("../types.mjs").TaxonomyListData | undefined}
- */
-export const useTaxonomyListDataResponse = () => {
- const response = useTaxonomyListData();
- if (response.status === 'success') {
- return response.data.data;
- }
- return undefined;
-};
-
-/**
- * @returns {boolean}
- */
-export const useIsTaxonomyListDataLoaded = () => (
- useTaxonomyListData().status === 'success'
-);
diff --git a/src/taxonomy/data/api.js b/src/taxonomy/data/api.js
new file mode 100644
index 000000000..513f7fdaf
--- /dev/null
+++ b/src/taxonomy/data/api.js
@@ -0,0 +1,29 @@
+// @ts-check
+import { camelCaseObject, getConfig } from '@edx/frontend-platform';
+import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
+
+const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
+export const getTaxonomyListApiUrl = () => new URL('api/content_tagging/v1/taxonomies/?enabled=true', getApiBaseUrl()).href;
+export const getExportTaxonomyApiUrl = (pk, format) => new URL(
+ `api/content_tagging/v1/taxonomies/${pk}/export/?output_format=${format}&download=1`,
+ getApiBaseUrl(),
+).href;
+
+/**
+ * Get list of taxonomies.
+ * @returns {Promise