diff --git a/package.json b/package.json index c72f2616f..e27f01c88 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "build": "fedx-scripts webpack", "i18n_extract": "fedx-scripts formatjs extract", "lint": "fedx-scripts eslint --ext .js --ext .jsx .", + "lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .", "start": "fedx-scripts webpack-dev-server --progress", "debug-test": "node --inspect-brk node_modules/.bin/jest --coverage --runInBand", "test": "TZ=UTC fedx-scripts jest --coverage --maxWorkers=2", diff --git a/src/Configuration/Customers/CustomerDetailView/CustomerCard.jsx b/src/Configuration/Customers/CustomerDetailView/CustomerCard.jsx index cf3df68f3..a90ce3a14 100644 --- a/src/Configuration/Customers/CustomerDetailView/CustomerCard.jsx +++ b/src/Configuration/Customers/CustomerDetailView/CustomerCard.jsx @@ -10,9 +10,10 @@ import { import { Launch, ContentCopy } from '@openedx/paragon/icons'; import { getConfig } from '@edx/frontend-platform'; import { formatDate, useCopyToClipboard } from '../data/utils'; +import DJANGO_ADMIN_BASE_URL from '../data/constants'; const CustomerCard = ({ enterpriseCustomer }) => { - const { ADMIN_PORTAL_BASE_URL, LMS_BASE_URL } = getConfig(); + const { ADMIN_PORTAL_BASE_URL } = getConfig(); const { showToast, copyToClipboard, setShowToast } = useCopyToClipboard(); return ( @@ -25,7 +26,7 @@ const CustomerCard = ({ enterpriseCustomer }) => { + + +); + +CustomerViewCard.propTypes = { + header: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + subtext: PropTypes.string.isRequired, + buttonText: PropTypes.string.isRequired, + buttonLink: PropTypes.string.isRequired, +}; + +export default CustomerViewCard; diff --git a/src/Configuration/Customers/CustomerDetailView/CustomerViewContainer.jsx b/src/Configuration/Customers/CustomerDetailView/CustomerViewContainer.jsx index ee4fc809c..72d67fcf6 100644 --- a/src/Configuration/Customers/CustomerDetailView/CustomerViewContainer.jsx +++ b/src/Configuration/Customers/CustomerDetailView/CustomerViewContainer.jsx @@ -10,6 +10,7 @@ import { import { useIntl } from '@edx/frontend-platform/i18n'; import CustomerCard from './CustomerCard'; import { getEnterpriseCustomer } from '../data/utils'; +import CustomerIntegrations from './CustomerIntegrations'; const CustomerViewContainer = () => { const { id } = useParams(); @@ -58,6 +59,12 @@ const CustomerViewContainer = () => { {!isLoading ? : } + diff --git a/src/Configuration/Customers/CustomerDetailView/tests/CustomerViewIntegrations.test.jsx b/src/Configuration/Customers/CustomerDetailView/tests/CustomerViewIntegrations.test.jsx new file mode 100644 index 000000000..ab99e6e88 --- /dev/null +++ b/src/Configuration/Customers/CustomerDetailView/tests/CustomerViewIntegrations.test.jsx @@ -0,0 +1,67 @@ +/* eslint-disable react/prop-types */ +import { screen, render, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom'; + +import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { formatDate } from '../../data/utils'; +import CustomerIntegrations from '../CustomerIntegrations'; + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ id: 'test-id' }), +})); + +jest.mock('../../data/utils', () => ({ + formatDate: jest.fn(), +})); + +const mockSSOData = [{ + enterpriseCustomer: '18005882300', + created: '2024-09-15T11:01:04.501365Z', + modified: '2024-09-15T11:01:04.501365Z', + displayName: 'Orange cats rule', +}]; + +const mockIntegratedChannelData = [ + { + channelCode: 'MOODLE', + enterpriseCustomer: '18005882300', + lastModifiedAt: '2024-09-15T11:01:04.501365Z', + }, + { + channelCode: 'CANVAS', + enterpriseCustomer: '18005882300', + lastModifiedAt: '2024-09-15T11:01:04.501365Z', + }, +]; + +describe('CustomerViewIntegrations', () => { + it('renders cards', async () => { + formatDate.mockReturnValue('September 15, 2024'); + render( + + + , + ); + await waitFor(() => { + expect(screen.getByText('Associated Integrations')).toBeInTheDocument(); + + expect(screen.getByText('SSO')).toBeInTheDocument(); + expect(screen.getByText('Orange cats rule')).toBeInTheDocument(); + expect(screen.getAllByText('Created September 15, 2024 • Last modified September 15, 2024')).toHaveLength(3); + expect(screen.getAllByText('Open in Admin Portal')).toHaveLength(3); + + expect(screen.getAllByText('LEARNING PLATFORM')).toHaveLength(2); + expect(screen.getByText('Moodle')).toBeInTheDocument(); + expect(screen.getByText('Canvas')).toBeInTheDocument(); + + expect(screen.getByText('INTEGRATION')).toBeInTheDocument(); + expect(screen.getByText('API')).toBeInTheDocument(); + }); + }); +}); diff --git a/src/Configuration/Customers/data/constants.js b/src/Configuration/Customers/data/constants.js new file mode 100644 index 000000000..bfe689256 --- /dev/null +++ b/src/Configuration/Customers/data/constants.js @@ -0,0 +1,3 @@ +const DJANGO_ADMIN_BASE_URL = 'https://internal.courses.edx.org'; + +export default DJANGO_ADMIN_BASE_URL; diff --git a/src/data/services/EnterpriseApiService.js b/src/data/services/EnterpriseApiService.js index d185c386d..bcb0e1400 100644 --- a/src/data/services/EnterpriseApiService.js +++ b/src/data/services/EnterpriseApiService.js @@ -18,6 +18,10 @@ class LmsApiService { static enterpriseCatalogsUrl = `${LmsApiService.enterpriseAPIBaseUrl}enterprise_catalogs/`; + static enterpriseSSOConfigurations = `${LmsApiService.enterpriseAPIBaseUrl}enterprise_customer_sso_configuration/`; + + static integratedChannelsUrl = `${LmsApiService.baseUrl}/integrated_channels/api/v1/configs/`; + static fetchEnterpriseCatalogQueries = () => LmsApiService.apiClient().get(LmsApiService.enterpriseCatalogQueriesUrl); static fetchEnterpriseCustomersBasicList = (enterpriseNameOrUuid) => LmsApiService.apiClient().get(`${LmsApiService.enterpriseCustomersBasicListUrl}${enterpriseNameOrUuid !== undefined ? `?name_or_uuid=${enterpriseNameOrUuid}` : ''}`); @@ -121,6 +125,24 @@ class LmsApiService { static fetchSubsidyAccessPolicies = async (enterpriseCustomerUuid) => LmsApiService.apiClient().get( `${getConfig().ENTERPRISE_ACCESS_BASE_URL}/api/v1/subsidy-access-policies/?enterprise_customer_uuid=${enterpriseCustomerUuid}`, ); + + static fetchEnterpriseCustomerSSOConfigs = (options) => { + const queryParams = new URLSearchParams({ + ...options, + }); + return LmsApiService.apiClient().get( + `${LmsApiService.enterpriseSSOConfigurations}?${queryParams.toString()}`, + ); + }; + + static fetchIntegratedChannels = (options) => { + const queryParams = new URLSearchParams({ + ...options, + }); + return LmsApiService.apiClient().get( + `${LmsApiService.integratedChannelsUrl}?${queryParams.toString()}`, + ); + }; } export default LmsApiService;