From 3becb387f420024a8822a433e565ae4cb1a1d4b4 Mon Sep 17 00:00:00 2001 From: Troy Sankey Date: Thu, 16 Nov 2023 20:22:06 -0800 Subject: [PATCH] squash me --- .../ProvisioningFormCustomCatalogDropdown.jsx | 3 +- ...visioningFormDefineCustomCatalogHeader.jsx | 2 +- .../PolicyForm/ProvisioningFormCatalog.jsx | 4 +- .../ProvisioningFormSubmissionButton.jsx | 8 +- .../ProvisioningFormSubmissionButton.test.jsx | 14 ++-- .../AssociatedCatalogDetail.jsx | 42 +++------- .../PolicyDetailView/CustomCatalogDetail.jsx | 4 +- .../PolicyDetailView/PolicyContainer.jsx | 40 +++------- .../PolicyDetailView/PolicyDescription.jsx | 20 +++-- .../PolicyDetailView/PolicyDetail.jsx | 29 ++++--- .../PolicyDetailView/PolicyDetailHeader.jsx | 29 +++---- .../PolicyDetailView/PolicyLimitsDetail.jsx | 37 ++++----- .../SubsidyDetailView/SubsidyDetailView.jsx | 79 +++++++------------ .../SubsidyDetailViewContainer.jsx | 19 +++-- .../Provisioning/data/constants.js | 3 + src/Configuration/Provisioning/data/hooks.js | 12 +-- .../Provisioning/data/tests/utils.test.js | 22 +++--- src/Configuration/Provisioning/data/utils.js | 3 +- .../ProvisioningContextWrapper.jsx | 4 +- 19 files changed, 154 insertions(+), 220 deletions(-) diff --git a/src/Configuration/Provisioning/ProvisioningForm/CustomCatalog/ProvisioningFormCustomCatalogDropdown.jsx b/src/Configuration/Provisioning/ProvisioningForm/CustomCatalog/ProvisioningFormCustomCatalogDropdown.jsx index a6d399220..6ab14ccba 100644 --- a/src/Configuration/Provisioning/ProvisioningForm/CustomCatalog/ProvisioningFormCustomCatalogDropdown.jsx +++ b/src/Configuration/Provisioning/ProvisioningForm/CustomCatalog/ProvisioningFormCustomCatalogDropdown.jsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { Form, Button } from '@edx/paragon'; import { v4 as uuidv4 } from 'uuid'; import PROVISIONING_PAGE_TEXT from '../../data/constants'; @@ -40,7 +40,6 @@ const ProvisioningFormCustomCatalogDropdown = () => { const handleClick = (e) => { // TODO: In the future the index will have to be brought in for custom catalogs. - const index = 0; const currentTarget = e.currentTarget; setPredefinedQueryType(undefined, index); setCatalogUuid(currentTarget.getAttribute('data-cataloguuid'), index); diff --git a/src/Configuration/Provisioning/ProvisioningForm/CustomCatalog/ProvisioningFormDefineCustomCatalogHeader.jsx b/src/Configuration/Provisioning/ProvisioningForm/CustomCatalog/ProvisioningFormDefineCustomCatalogHeader.jsx index 4459a3a08..e1351d643 100644 --- a/src/Configuration/Provisioning/ProvisioningForm/CustomCatalog/ProvisioningFormDefineCustomCatalogHeader.jsx +++ b/src/Configuration/Provisioning/ProvisioningForm/CustomCatalog/ProvisioningFormDefineCustomCatalogHeader.jsx @@ -28,7 +28,7 @@ const ProvisioningFormDefineCustomCatalogHeader = ({ index }) => { { - // Only render the warning header if we plan to display a catalog selector drop-down. + // Only render the warning header if we plan to display a catalog selector drop-down. !formData.policies[index].customCatalog && ( diff --git a/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/ProvisioningFormCatalog.jsx b/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/ProvisioningFormCatalog.jsx index 5447f9869..72521f795 100644 --- a/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/ProvisioningFormCatalog.jsx +++ b/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/ProvisioningFormCatalog.jsx @@ -6,7 +6,7 @@ import { v4 as uuidv4 } from 'uuid'; import { useContextSelector } from 'use-context-selector'; import PROVISIONING_PAGE_TEXT from '../../data/constants'; import useProvisioningContext from '../../data/hooks'; -import { generateBudgetDisplayName, getCamelCasedConfigAttribute, indexOnlyPropType } from '../../data/utils'; +import { generateBudgetDisplayName, indexOnlyPropType } from '../../data/utils'; import { ProvisioningContext } from '../../ProvisioningContext'; // TODO: Replace URL for hyperlink to somewhere to display catalog content information @@ -27,7 +27,6 @@ const ProvisioningFormCatalog = ({ index }) => { hasEdits, } = contextData; const isFormFieldInvalid = policies[index]?.predefinedQueryType === false; - const camelCasedQueries = getCamelCasedConfigAttribute('PREDEFINED_CATALOG_QUERIES'); let submittedFormAssociatedCatalog; if (isEditMode && !multipleFunds) { @@ -39,7 +38,6 @@ const ProvisioningFormCatalog = ({ index }) => { } const [value, setValue] = useState(submittedFormAssociatedCatalog || null); - const customCatalogSelected = value === CATALOG.OPTIONS.custom; if (multipleFunds === undefined) { return null; } diff --git a/src/Configuration/Provisioning/ProvisioningForm/ProvisioningFormSubmissionButton.jsx b/src/Configuration/Provisioning/ProvisioningForm/ProvisioningFormSubmissionButton.jsx index 00e6a2fab..0c8821a45 100644 --- a/src/Configuration/Provisioning/ProvisioningForm/ProvisioningFormSubmissionButton.jsx +++ b/src/Configuration/Provisioning/ProvisioningForm/ProvisioningFormSubmissionButton.jsx @@ -171,9 +171,9 @@ const ProvisioningFormSubmissionButton = () => { const { customAttributes } = error; if (customAttributes) { logError( - 'Alert Error: ' + - `${API_ERROR_MESSAGES.ENTERPRISE_CUSTOMER_CATALOG_CREATION[customAttributes.httpErrorStatus]} ` + - `${error}` + 'Alert Error: ' + + `${API_ERROR_MESSAGES.ENTERPRISE_CUSTOMER_CATALOG_CREATION[customAttributes.httpErrorStatus]} ` + + `${error}`, ); redirectOnError( customAttributes.httpErrorStatus, @@ -264,7 +264,7 @@ const ProvisioningFormSubmissionButton = () => { complete: BUTTON.success, error: BUTTON.error, }; - console.log(formData); // TEST + console.log(formData); // TEST return ( { const originalModule = jest.requireActual('../../data/utils'); return { ...originalModule, - //createCatalogs: jest.fn(), + // createCatalogs: jest.fn(), createPolicy: jest.fn(), createSubsidy: jest.fn(), determineInvalidFields: jest.fn().mockReturnValue([ @@ -94,7 +94,7 @@ describe('ProvisioningFormSubmissionButton', () => { }); for (let i = 0; i < sampleDataSet.length; i++) { it(`calls handleSubmit complete state when clicked with ${Object.keys(sampleDataSet[i])} data`, async () => { - //createCatalogs.mockResolvedValue({ uuid: 'test-uuid' }); + // createCatalogs.mockResolvedValue({ uuid: 'test-uuid' }); createSubsidy.mockResolvedValue({ uuid: 'test-uuid' }); createPolicy.mockResolvedValue({ uuid: 'test-uuid' }); const value = { @@ -114,7 +114,7 @@ describe('ProvisioningFormSubmissionButton', () => { error.customAttributes = { httpErrorStatus: 500, }; - //createCatalogs.mockRejectedValue(error); + // createCatalogs.mockRejectedValue(error); const value = { ...initialStateValue, formData: sampleDataSet[0][Object.keys(sampleDataSet[0])], @@ -131,7 +131,7 @@ describe('ProvisioningFormSubmissionButton', () => { error.customAttributes = { httpErrorStatus: 500, }; - //createCatalogs.mockResolvedValue({ uuid: 'test-catalog-uuid' }); + // createCatalogs.mockResolvedValue({ uuid: 'test-catalog-uuid' }); createSubsidy.mockRejectedValue(error); const value = { ...initialStateValue, @@ -149,7 +149,7 @@ describe('ProvisioningFormSubmissionButton', () => { error.customAttributes = { httpErrorStatus: 500, }; - //createCatalogs.mockResolvedValue({ uuid: 'test-catalog-uuid' }); + // createCatalogs.mockResolvedValue({ uuid: 'test-catalog-uuid' }); createSubsidy.mockResolvedValue({ uuid: 'test-subsidy-uuid' }); createPolicy.mockRejectedValue(error); diff --git a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/AssociatedCatalogDetail.jsx b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/AssociatedCatalogDetail.jsx index 191a2444f..d0076e0ed 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/AssociatedCatalogDetail.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/AssociatedCatalogDetail.jsx @@ -1,47 +1,29 @@ -import PropTypes from 'prop-types'; import CustomCatalogDetail from './CustomCatalogDetail'; import PROVISIONING_PAGE_TEXT from '../../data/constants'; +import { indexOnlyPropType, selectProvisioningContext } from '../../data/utils'; -const { FORM: { CATALOG } } = PROVISIONING_PAGE_TEXT; +const { FORM } = PROVISIONING_PAGE_TEXT; -// finds the catalog in associatedCatalog string, -// e.g. "9c1fd12b-2365-4100-8e3e-01d2ff1414e0 - Executive Education budget" -// returns "Executive Education" -function getCatalogType(associatedCatalog) { - let catalogType = null; - if (associatedCatalog) { - if (associatedCatalog.includes(CATALOG.OPTIONS.openCourses)) { - catalogType = CATALOG.OPTIONS.openCourses; - } else if (associatedCatalog.includes(CATALOG.OPTIONS.executiveEducation)) { - catalogType = CATALOG.OPTIONS.executiveEducation; - } else if (associatedCatalog.includes(CATALOG.OPTIONS.everything)) { - catalogType = CATALOG.OPTIONS.everything; - } else { - catalogType = CATALOG.OPTIONS.custom; - } - } - return catalogType; -} - -const AssociatedCatalogDetail = ({ associatedCatalog }) => { - const catalogType = getCatalogType(associatedCatalog); +const AssociatedCatalogDetail = ({ index }) => { + const [formData] = selectProvisioningContext('formData'); return (
-

{CATALOG.TITLE}

+

{FORM.CATALOG.TITLE}

-

{CATALOG.SUB_TITLE}

+

{FORM.CATALOG.SUB_TITLE}

- {catalogType} + {FORM.CATALOG.OPTIONS[formData.policies[index].predefinedQueryType]}

- {(catalogType === CATALOG.OPTIONS.custom) && } + { + (formData.policies[index].predefinedQueryType === FORM.CATALOG.OPTIONS.custom) + && + }
); }; -AssociatedCatalogDetail.propTypes = { - associatedCatalog: PropTypes.string.isRequired, -}; +AssociatedCatalogDetail.propTypes = indexOnlyPropType; export default AssociatedCatalogDetail; diff --git a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/CustomCatalogDetail.jsx b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/CustomCatalogDetail.jsx index b2c4359b7..bc58fb5e4 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/CustomCatalogDetail.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/CustomCatalogDetail.jsx @@ -60,9 +60,9 @@ const CustomCatalogDetail = ({ catalogTitle }) => { return ( !isLoading ? (
-

{CUSTOM_CATALOG.HEADER.DEFINE.TITLE}

+

{CUSTOM_CATALOG.DETAIL_HEADER.TITLE}

-
{CUSTOM_CATALOG.OPTIONS.enterpriseCatalogQuery.title}
+
{CUSTOM_CATALOG.OPTIONS.enterpriseCatalog.title}

{catalogTitle}

diff --git a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyContainer.jsx b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyContainer.jsx index d423af91a..aca2392da 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyContainer.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyContainer.jsx @@ -4,35 +4,19 @@ import PolicyDescription from './PolicyDescription'; import PolicyDetail from './PolicyDetail'; import PolicyDetailHeader from './PolicyDetailHeader'; import PolicyLimitsDetail from './PolicyLimitsDetail'; +import { selectProvisioningContext } from '../../data/utils'; -function getBudgetDisplayName(subsidyTitle, catalogTitle) { - let budgetDisplayName; - if (subsidyTitle && catalogTitle) { - const associatedCatalog = catalogTitle.split(' - ')[1]; - budgetDisplayName = `${subsidyTitle} - ${associatedCatalog}`; - } - return budgetDisplayName; -} - -const PolicyContainer = ({ data }) => { - const { subsidy, policies, catalogs } = data; - const renderPolicy = policies.map((policy) => catalogs.map(catalog => { - if (catalog.uuid === policy.catalog_uuid) { - return ( - - - - - - - - ); - } - return null; - })); +const PolicyContainer = () => { + const [formData] = selectProvisioningContext('formData'); + const renderPolicy = formData.policies.map((policy, index) => ( + + + + + + + + )); return renderPolicy; }; diff --git a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDescription.jsx b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDescription.jsx index e670b747d..2943929d0 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDescription.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDescription.jsx @@ -1,18 +1,16 @@ import PropTypes from 'prop-types'; import PROVISIONING_PAGE_TEXT from '../../data/constants'; -const PolicyDescription = ({ description }) => { - const { FORM: { ACCOUNT_DESCRIPTION } } = PROVISIONING_PAGE_TEXT; +const { FORM } = PROVISIONING_PAGE_TEXT; - return ( -
-

{ACCOUNT_DESCRIPTION.TITLE}

-

- {description} -

-
- ); -}; +const PolicyDescription = ({ description }) => ( +
+

{FORM.ACCOUNT_DESCRIPTION.TITLE}

+

+ {description} +

+
+); PolicyDescription.propTypes = { description: PropTypes.string.isRequired, diff --git a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDetail.jsx b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDetail.jsx index 43b30c5d9..eabe99ed5 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDetail.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDetail.jsx @@ -1,31 +1,34 @@ -import PropTypes from 'prop-types'; import PROVISIONING_PAGE_TEXT from '../../data/constants'; -import { formatCurrency } from '../../data/utils'; +import { + formatCurrency, + generatePolicyName, + indexOnlyPropType, + selectProvisioningContext, +} from '../../data/utils'; -const PolicyDetail = ({ displayName, spendLimit }) => { - const { FORM: { ACCOUNT_TYPE, ACCOUNT_DETAIL } } = PROVISIONING_PAGE_TEXT; +const { FORM } = PROVISIONING_PAGE_TEXT; + +const PolicyDetail = ({ index }) => { + const [formData] = selectProvisioningContext('formData'); return (

Default

-

{ACCOUNT_DETAIL.TITLE}

+

{FORM.ACCOUNT_DETAIL.TITLE}

-

{ACCOUNT_DETAIL.OPTIONS.displayName}

+

{FORM.ACCOUNT_DETAIL.OPTIONS.displayName}

- {displayName} + {generatePolicyName(formData, index)}

-

{ACCOUNT_DETAIL.OPTIONS.totalAccountValue.title}

+

{FORM.ACCOUNT_DETAIL.OPTIONS.totalAccountValue.title}

- {formatCurrency(spendLimit)} + {formatCurrency(formData.policies[index].accountValue)}

); }; -PolicyDetail.propTypes = { - displayName: PropTypes.string.isRequired, - spendLimit: PropTypes.number.isRequired, -}; +PolicyDetail.propTypes = indexOnlyPropType; export default PolicyDetail; diff --git a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDetailHeader.jsx b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDetailHeader.jsx index 00e643265..a8365142f 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDetailHeader.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyDetailHeader.jsx @@ -1,33 +1,22 @@ -import PropTypes from 'prop-types'; -import PROVISIONING_PAGE_TEXT, { PREDEFINED_QUERY_DISPLAY_NAMES } from '../../data/constants'; +import { + indexOnlyPropType, + selectProvisioningContext, + generateBudgetDisplayName, +} from '../../data/utils'; -const PolicyDetailHeader = ({ accountType, policiesLength }) => { - const { FORM: { CATALOG } } = PROVISIONING_PAGE_TEXT; - const renderAccountType = () => { - let account; - if (policiesLength > 1 && accountType.includes(CATALOG.OPTIONS.executiveEducation)) { - account = `${PREDEFINED_QUERY_DISPLAY_NAMES.executiveEducation} budget`; - } else if (policiesLength > 1 && accountType.includes(CATALOG.OPTIONS.openCourses)) { - account = `${PREDEFINED_QUERY_DISPLAY_NAMES.openCourses} budget`; - } else { - account = 'Budget'; - } - return account; - }; +const PolicyDetailHeader = ({ index }) => { + const [formData] = selectProvisioningContext('formData'); return (
-

{renderAccountType()}

+

{generateBudgetDisplayName(formData.policies[index])}


); }; -PolicyDetailHeader.propTypes = { - accountType: PropTypes.string.isRequired, - policiesLength: PropTypes.number.isRequired, -}; +PolicyDetailHeader.propTypes = indexOnlyPropType; export default PolicyDetailHeader; diff --git a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyLimitsDetail.jsx b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyLimitsDetail.jsx index d2b7a13a8..a93ad9a78 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyLimitsDetail.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/PolicyDetailView/PolicyLimitsDetail.jsx @@ -1,25 +1,32 @@ -import PropTypes from 'prop-types'; import PROVISIONING_PAGE_TEXT from '../../data/constants'; -import { formatCurrency } from '../../data/utils'; +import { + // formatCurrency, + indexOnlyPropType, + selectProvisioningContext, +} from '../../data/utils'; -const PolicyLimitsDetail = ({ perLearnerLimit }) => { - const { FORM: { LEARNER_CAP, LEARNER_CAP_DETAIL } } = PROVISIONING_PAGE_TEXT; +// TODO: Use formatCurrency (FIRST UPDATE STATE TO STORE CENTS IN formData.policies[index].perLearnerCapAmount). + +const { FORM } = PROVISIONING_PAGE_TEXT; + +const PolicyLimitsDetail = ({ index }) => { + const [formData] = selectProvisioningContext('formData'); return (
-

{LEARNER_CAP.TITLE}

+

{FORM.LEARNER_CAP.TITLE}

-

{LEARNER_CAP.SUB_TITLE}

+

{FORM.LEARNER_CAP.SUB_TITLE}

- {perLearnerLimit ? LEARNER_CAP.OPTIONS.yes : LEARNER_CAP.OPTIONS.no} + {formData.policies[index].perLearnerCap ? FORM.LEARNER_CAP.OPTIONS.yes : FORM.LEARNER_CAP.OPTIONS.no}

- {perLearnerLimit ? ( + {formData.policies[index].perLearnerCap ? (
-

{LEARNER_CAP_DETAIL.TITLE}

-
{LEARNER_CAP_DETAIL.OPTIONS.perLearnerSpendCap.title}
+

{FORM.LEARNER_CAP_DETAIL.TITLE}

+
{FORM.LEARNER_CAP_DETAIL.OPTIONS.perLearnerSpendCap.title}

- {formatCurrency(perLearnerLimit)} + {formData.policies[index].perLearnerCapAmount}

) : null} @@ -27,12 +34,6 @@ const PolicyLimitsDetail = ({ perLearnerLimit }) => { ); }; -PolicyLimitsDetail.propTypes = { - perLearnerLimit: PropTypes.number, -}; - -PolicyLimitsDetail.defaultProps = { - perLearnerLimit: null, -}; +PolicyLimitsDetail.propTypes = indexOnlyPropType; export default PolicyLimitsDetail; diff --git a/src/Configuration/Provisioning/SubsidyDetailView/SubsidyDetailView.jsx b/src/Configuration/Provisioning/SubsidyDetailView/SubsidyDetailView.jsx index 620e16942..bb4905637 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/SubsidyDetailView.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/SubsidyDetailView.jsx @@ -1,5 +1,6 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; +import { useContextSelector } from 'use-context-selector'; import { logError } from '@edx/frontend-platform/logging'; import AccountTypeDetail from './AccountTypeDetail'; @@ -13,21 +14,24 @@ import TermDetail from './TermDetail'; import TitleDetail from './TitleDetail'; import PolicyContainer from './PolicyDetailView/PolicyContainer'; import PageLoading from '../../../components/common/PageLoading'; -import { - getCatalog, getCustomer, getPolicies, getPoliciesForSubsidy, getSubsidy, -} from '../data/utils'; +import useProvisioningContext from '../data/hooks'; +import { ProvisioningContext } from '../ProvisioningContext'; const SubsidyDetailView = () => { const navigate = useNavigate(); const { FORM } = PROVISIONING_PAGE_TEXT; - const [isLoading, setIsLoading] = useState(true); const { SUB_DIRECTORY: { ERROR } } = ROUTES.CONFIGURATION.SUB_DIRECTORY.PROVISIONING; const params = useParams(); const subsidyUuid = params.id; - const [enterpriseSubsidiesData, setEnterpriseSubsidiesData] = useState({}); + const contextData = useContextSelector(ProvisioningContext, v => v[0]); + const { + formData, + isLoading, + } = contextData; + const { hydrateEnterpriseSubsidiesData } = useProvisioningContext(); const redirectOnError = (statusCode, message) => { navigate(ERROR, { @@ -38,42 +42,13 @@ const SubsidyDetailView = () => { }; useEffect(() => { - const fetchEnterpriseSubsidiesData = async () => { - try { - const subsidy = await getSubsidy(subsidyUuid); - const subsidyCustomerId = subsidy.data.results[0].enterprise_customer_uuid; - const [customerResponse, policiesForCustomerResponse] = await Promise.all([ - getCustomer(subsidyCustomerId), getPolicies(subsidyCustomerId), - ]); - const policiesData = getPoliciesForSubsidy(policiesForCustomerResponse, subsidyUuid); - setEnterpriseSubsidiesData((prevState) => ({ - ...prevState, - subsidy: { - ...subsidy.data.results[0], - }, - customer: { - ...customerResponse.data[0], - }, - policies: policiesData, - })); - - const catalogs = await Promise.all(policiesData.map(async (policyData) => { - const catalog = await getCatalog(policyData.catalog_uuid); - return catalog; - })); - - setEnterpriseSubsidiesData((prevState) => ({ - ...prevState, - catalogs, - })); - setIsLoading(false); - } catch (error) { - const { customAttributes } = error; - logError(error); - redirectOnError(customAttributes?.httpErrorStatus, error); - } - }; - fetchEnterpriseSubsidiesData(); + try { + hydrateEnterpriseSubsidiesData(subsidyUuid); + } catch (error) { + const { customAttributes } = error; + logError(error); + redirectOnError(customAttributes?.httpErrorStatus, error); + } }, [subsidyUuid]); return ( @@ -83,20 +58,20 @@ const SubsidyDetailView = () => {

{FORM.SUB_TITLE}


- + - - - 1} /> - {enterpriseSubsidiesData?.policies ? : null} + + + 1} /> + {formData.policies ? : null}
) : diff --git a/src/Configuration/Provisioning/SubsidyDetailView/SubsidyDetailViewContainer.jsx b/src/Configuration/Provisioning/SubsidyDetailView/SubsidyDetailViewContainer.jsx index 34b7f49ae..777b941b2 100644 --- a/src/Configuration/Provisioning/SubsidyDetailView/SubsidyDetailViewContainer.jsx +++ b/src/Configuration/Provisioning/SubsidyDetailView/SubsidyDetailViewContainer.jsx @@ -3,19 +3,22 @@ import { ActionRow, Container } from '@edx/paragon'; import EditButton from './EditButton'; import SubsidyDetailView from './SubsidyDetailView'; import PROVISIONING_PAGE_TEXT from '../data/constants'; +import ProvisioningContextProvider from '../ProvisioningContext'; const SubsidyDetailViewContainer = () => { const { pathname } = useLocation(); const { FORM } = PROVISIONING_PAGE_TEXT; return ( - - -

{FORM.TITLE(pathname)}

- - -
- -
+ + + +

{FORM.TITLE(pathname)}

+ + +
+ +
+
); }; diff --git a/src/Configuration/Provisioning/data/constants.js b/src/Configuration/Provisioning/data/constants.js index 2cc9c1cec..12a23e04a 100644 --- a/src/Configuration/Provisioning/data/constants.js +++ b/src/Configuration/Provisioning/data/constants.js @@ -132,6 +132,9 @@ const PROVISIONING_PAGE_TEXT = { TITLE: 'Select existing unique/curated enterprise catalog', WARN_SUB_TITLE: 'Ensure the intended enterprise catalog has been created in Django Admin before proceeding.', }, + DETAIL_HEADER: { + TITLE: 'Select existing unique/curated enterprise catalog', + }, BUTTON: { createCatalog: 'Create catalog', }, diff --git a/src/Configuration/Provisioning/data/hooks.js b/src/Configuration/Provisioning/data/hooks.js index 94c2ed4cd..fba560fcb 100644 --- a/src/Configuration/Provisioning/data/hooks.js +++ b/src/Configuration/Provisioning/data/hooks.js @@ -203,7 +203,6 @@ export default function useProvisioningContext() { setState(s => ({ ...s, existingEnterpriseCatalogs: { - //...s.enterpriseCatalogs, // not sure why this is needed data: camelCaseObject(data.results), isLoading: false, }, @@ -233,19 +232,13 @@ export default function useProvisioningContext() { return catalog; })); - let customCatalog; const policiesData = policiesResponseData.map(policy => { const formattedPolicies = []; const { queryIdToQueryType } = getPredefinedCatalogQueryMappings(); catalogs.forEach(catalog => { - const allPredefinedQueryIds = Object.keys(queryIdToQueryType); if (catalog.uuid === policy.catalog_uuid) { const predefinedQueryType = queryIdToQueryType[catalog.enterprise_catalog_query]; - if (!predefinedQueryType) { - // We encountered at least one policy with a custom catalog. This will be used one level up. - customCatalog = true; - } formattedPolicies.push({ accountDescription: policy.description, accountValue: policy.spend_limit, @@ -256,8 +249,11 @@ export default function useProvisioningContext() { // Set both old and current catalog values to identical values, to start. // Old values should remain static and will help us later decide whether to skip catalog creation. oldPredefinedQueryType: predefinedQueryType, + oldCustomCatalog: !predefinedQueryType, oldCatalogUuid: catalog.uuid, + // New values will change over time as different options are selected. predefinedQueryType, + customCatalog: !predefinedQueryType, catalogUuid: catalog.uuid, // We ostensibly don't rely on the catalog title for anything critical, but in case it is a custom catalog // we can cache the title here so that we have something to display in the detail view header. @@ -294,7 +290,6 @@ export default function useProvisioningContext() { subsidyTitle: !!subsidyData?.title, }, multipleFunds: isMultipleFunds, - customCatalog, isLoading: false, })); }, [setState]); @@ -302,7 +297,6 @@ export default function useProvisioningContext() { const resetFormData = useCallback(() => { setState(() => ({ multipleFunds: undefined, - customCatalog: false, formData: { policies: [], }, diff --git a/src/Configuration/Provisioning/data/tests/utils.test.js b/src/Configuration/Provisioning/data/tests/utils.test.js index 6cb971f9d..144471317 100644 --- a/src/Configuration/Provisioning/data/tests/utils.test.js +++ b/src/Configuration/Provisioning/data/tests/utils.test.js @@ -1,12 +1,12 @@ import { camelCaseObject } from '@edx/frontend-platform'; import { - createCatalog, + getOrCreateCatalog, createPolicy, createSubsidy, determineInvalidFields, // extractDefinedCatalogTitle, filterByEnterpriseCustomerName, - filterIndexOfCatalogQueryTitle, + // filterIndexOfCatalogQueryTitle, getCamelCasedConfigAttribute, // getCatalogUuid, getCatalogQueries, @@ -27,7 +27,7 @@ import { // sampleCatalogs, sampleDataTableData, sampleMultiplePolicyFormData, - samplePolicyResponse, + // samplePolicyResponse, sampleSinglePolicyCustomCatalogQueryFormData, sampleSinglePolicyPredefinedCatalogQueryFormData, } from '../../../testData/constants'; @@ -110,7 +110,11 @@ describe('getCamelCasedConfigAttribute', () => { // expect(extractDefinedCatalogTitle({})).toEqual(null); // }); // it('returns catalog query title', () => { -// expect(extractDefinedCatalogTitle({ catalogQueryMetadata: { catalogQuery: { title: 'The Bestests' } } })).toEqual('The Bestests'); +// expect( +// extractDefinedCatalogTitle({ catalogQueryMetadata: { catalogQuery: { title: 'The Bestests' } } }) +// ).toEqual( +// 'The Bestests' +// ); // }); // }); @@ -202,7 +206,7 @@ describe('getCatalogQueries', () => { const sampleResponses = { data: { - createCatalog: { + getOrCreateCatalog: { uuid: 'abf9f43b-1872-4c26-a2e6-1598fc57fbdd', title: 'test123', enterprise_customer: 'c6aaf182-bcae-4d14-84cd-d538b7ec08f0', @@ -290,14 +294,14 @@ jest.mock('@edx/frontend-platform/auth', () => ({ }), })); -describe('createCatalog', () => { +describe('getOrCreateCatalog', () => { it('returns the correct data', async () => { - const data = await createCatalog([ + const data = await getOrCreateCatalog([ 'abf9f43b-1872-4c26-a2e6-1598fc57fbdd', 10, 'abf9f43b-1872-4c26-a2e6-1598fc57fbdd - test123', ]); - expect(data.createCatalog).toEqual(sampleResponses.data.createCatalog); + expect(data.getOrCreateCatalog).toEqual(sampleResponses.data.getOrCreateCatalog); }); }); @@ -451,7 +455,7 @@ describe('transformPatchPolicyData', () => { }], subsidyUuid: '205f11a4-0303-4407-a2e7-80261ef8fb8f', }; - const output = await transformPatchPolicyPayload(mockFormData, [samplePatchResponses.createCatalog]); + const output = await transformPatchPolicyPayload(mockFormData, [samplePatchResponses.getOrCreateCatalog]); expect(output).toEqual([{ description: 'awesome policy description', catalogUuid: '2afb0a7f-103d-43c3-8b1a-db8c5b3ba1f4', diff --git a/src/Configuration/Provisioning/data/utils.js b/src/Configuration/Provisioning/data/utils.js index 6f7220238..a68af87f1 100644 --- a/src/Configuration/Provisioning/data/utils.js +++ b/src/Configuration/Provisioning/data/utils.js @@ -169,7 +169,8 @@ export function hasValidPolicyAndSubsidy(formData) { } // returns true if all fields are valid for every policy - return isAccountNameValid && isAccountValueValid && isPredefinedQueryTypeValid && isPerLearnerCapValid; + return isAccountNameValid && isAccountValueValid && isPredefinedQueryTypeValid && isCatalogUuidValid + && isPerLearnerCapValid; }); // returns true if all fields are valid for subsidy fields and all policy fields diff --git a/src/Configuration/testData/Provisioning/ProvisioningContextWrapper.jsx b/src/Configuration/testData/Provisioning/ProvisioningContextWrapper.jsx index 56c2f1764..c86d49d90 100644 --- a/src/Configuration/testData/Provisioning/ProvisioningContextWrapper.jsx +++ b/src/Configuration/testData/Provisioning/ProvisioningContextWrapper.jsx @@ -43,7 +43,7 @@ export const hydratedInitialState = { subsidyUuid: '0196e5c3-ba08-4798-8bf1-019d747c27bf', subsidyTitle: 'Paper company', customerName: 'Dunder mifflin', - enterpriseUUID: customerUuid, + enterpriseUUID, internalOnly: true, financialIdentifier: '00k12sdf4', subsidyRevReq: 'Yes (bulk enrollment prepay)', @@ -58,7 +58,7 @@ export const hydratedInitialState = { accountName: 'Test Subsidy Title - Open Courses Budget', customCatalog: false, predefinedQueryType: PREDEFINED_QUERIES_ENUM.openCourses, - catalogTitle: `${customerUuid} --- ${PREDEFINED_QUERY_DISPLAY_NAMES.openCourses}`, + catalogTitle: `${enterpriseUUID} --- ${PREDEFINED_QUERY_DISPLAY_NAMES.openCourses}`, catalogUuid: uuidv4(), }, ],