From b27e35fd150ed6bd00d7c6c2868efab63c32e4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B4mulo=20Penido?= Date: Thu, 19 Oct 2023 10:06:04 -0300 Subject: [PATCH] feat: add taxonomy detail page --- src/index.jsx | 19 ++-- src/taxonomy/api/hooks/api.js | 25 +++++- src/taxonomy/api/hooks/selectors.js | 34 ++++++- src/taxonomy/api/types.mjs | 2 +- src/taxonomy/index.js | 2 +- .../taxonomy-detail/TaxonomyDetailPage.jsx | 89 +++++++++++++++++++ src/taxonomy/taxonomy-detail/index.js | 2 + 7 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 src/taxonomy/taxonomy-detail/TaxonomyDetailPage.jsx create mode 100644 src/taxonomy/taxonomy-detail/index.js diff --git a/src/index.jsx b/src/index.jsx index f671a90f84..8befe44044 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -22,7 +22,7 @@ import CourseAuthoringRoutes from './CourseAuthoringRoutes'; import Head from './head/Head'; import { StudioHome } from './studio-home'; import CourseRerun from './course-rerun'; -import { TaxonomyListPage } from './taxonomy'; +import { TaxonomyDetailPage, TaxonomyListPage } from './taxonomy'; import 'react-datepicker/dist/react-datepicker.css'; import './index.scss'; @@ -71,11 +71,18 @@ const App = () => { }} /> {process.env.ENABLE_TAGGING_TAXONOMY_PAGES === 'true' && ( - - - + <> + + { + const { params: { taxonomyId } } = match; + return ( + + ); + }} + /> + )} diff --git a/src/taxonomy/api/hooks/api.js b/src/taxonomy/api/hooks/api.js index 6da57c1719..81d8f00c47 100644 --- a/src/taxonomy/api/hooks/api.js +++ b/src/taxonomy/api/hooks/api.js @@ -5,7 +5,13 @@ 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; - +/** + * @param {number} taxonomyId + */ +const getTaxonomyDetailApiUrl = (taxonomyId) => new URL( + `api/content_tagging/v1/taxonomies/${taxonomyId}/`, + getApiBaseUrl(), +).href; /** * @returns {import("../types.mjs").UseQueryResult} */ @@ -13,8 +19,21 @@ const useTaxonomyListData = () => ( useQuery({ queryKey: ['taxonomyList'], queryFn: () => getAuthenticatedHttpClient().get(getTaxonomyListApiUrl) - .then(camelCaseObject), + .then(camelCaseObject).then(({ data }) => data), + }) +); + +/** + * @param {number} taxonomyId + * @returns {import('@tanstack/react-query').UseQueryResult} + */ +const useTaxonomyDetailData = (taxonomyId) => ( + useQuery({ + queryKey: ['taxonomyList', taxonomyId], + queryFn: () => getAuthenticatedHttpClient().get(getTaxonomyDetailApiUrl(taxonomyId)) + .then(camelCaseObject) + .then((response) => response.data), }) ); -export default useTaxonomyListData; +export { useTaxonomyListData, useTaxonomyDetailData }; diff --git a/src/taxonomy/api/hooks/selectors.js b/src/taxonomy/api/hooks/selectors.js index 6908827caf..159d7d0114 100644 --- a/src/taxonomy/api/hooks/selectors.js +++ b/src/taxonomy/api/hooks/selectors.js @@ -1,5 +1,5 @@ // @ts-check -import useTaxonomyListData from './api'; +import { useTaxonomyListData, useTaxonomyDetailData } from './api'; /** * @returns {import("../types.mjs").TaxonomyListData | undefined} @@ -18,3 +18,35 @@ export const useTaxonomyListDataResponse = () => { export const useIsTaxonomyListDataLoaded = () => ( useTaxonomyListData().status === 'success' ); + +/** + * @params {number} taxonomyId + * @returns {Pick} + */ +export const useTaxonomyDetailDataStatus = (taxonomyId) => { + const { + isError, + error, + isFetched, + isSuccess, + } = useTaxonomyDetailData(taxonomyId); + return { + isError, + error, + isFetched, + isSuccess, + }; +}; + +/** + * @params {number} taxonomyId + * @returns {import("../types.mjs").TaxonomyData | undefined} + */ +export const useTaxonomyDetailDataResponse = (taxonomyId) => { + const { isSuccess, data } = useTaxonomyDetailData(taxonomyId); + if (isSuccess) { + return data; + } + + return undefined; +}; diff --git a/src/taxonomy/api/types.mjs b/src/taxonomy/api/types.mjs index 980939b255..7c7f4c0677 100644 --- a/src/taxonomy/api/types.mjs +++ b/src/taxonomy/api/types.mjs @@ -1,6 +1,6 @@ // @ts-check -/** +/** * @typedef {Object} TaxonomyData * @property {number} id * @property {string} name diff --git a/src/taxonomy/index.js b/src/taxonomy/index.js index c857f10e6c..4fc3470bb7 100644 --- a/src/taxonomy/index.js +++ b/src/taxonomy/index.js @@ -1,2 +1,2 @@ -// eslint-disable-next-line import/prefer-default-export export { default as TaxonomyListPage } from './TaxonomyListPage'; +export { TaxonomyDetailPage } from './taxonomy-detail'; diff --git a/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.jsx b/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.jsx new file mode 100644 index 0000000000..a4036357f8 --- /dev/null +++ b/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.jsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { + Container, +} from '@edx/paragon'; +import Proptypes from 'prop-types'; + +import PermissionDeniedAlert from '../../generic/PermissionDeniedAlert'; +import Loading from '../../generic/Loading'; +import Header from '../../header'; +import SubHeader from '../../generic/sub-header/SubHeader'; +import { useTaxonomyDetailDataResponse, useTaxonomyDetailDataStatus } from '../api/hooks/selectors'; + + +const TaxonomyDetailTemp = ({ taxonomyId }) => { + const useTaxonomyDetailData = () => { + const { isError, isFetched } = useTaxonomyDetailDataStatus(taxonomyId); + const taxonomy = useTaxonomyDetailDataResponse(taxonomyId); + return { isError, isFetched, taxonomy }; + }; + + const { isError, isFetched, taxonomy } = useTaxonomyDetailData(taxonomyId); + + if (isError) { + return ( + + ); + } + + if (!isFetched) { + return ( + + ); + } + + if (taxonomy) { + return ( + <> +
+ + + +
+
+ + { + taxonomy ? ( +
+
{JSON.stringify(taxonomy, null, 2)}
+
+ ) : (<>Taxonomy not found) + } +
+
+ + ); + } + + return undefined; +}; + +const TaxonomyDetailPage = ({ taxonomyId }) => ( + <> + +
+ + +); + +TaxonomyDetailPage.propTypes = { + taxonomyId: Proptypes.number, +}; + +TaxonomyDetailPage.defaultProps = { + taxonomyId: undefined, +}; + +TaxonomyDetailTemp.propTypes = TaxonomyDetailPage.propTypes; +TaxonomyDetailTemp.defaultProps = TaxonomyDetailPage.defaultProps; + +export default TaxonomyDetailPage; diff --git a/src/taxonomy/taxonomy-detail/index.js b/src/taxonomy/taxonomy-detail/index.js new file mode 100644 index 0000000000..452695f08f --- /dev/null +++ b/src/taxonomy/taxonomy-detail/index.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export { default as TaxonomyDetailPage } from './TaxonomyDetailPage';