From a19fe04f456ac78e9647444649388982b5c5327a Mon Sep 17 00:00:00 2001
From: Kira Miller <31229189+kiram15@users.noreply.github.com>
Date: Wed, 3 Apr 2024 08:26:03 -0600
Subject: [PATCH] fix: hiding highlights for custom courses (#1191)
* fix: hiding highlights for custom courses
* fix: PR requests
---
src/components/Sidebar/index.jsx | 28 +++++++++++++++--
src/containers/Sidebar/Sidebar.test.jsx | 41 +++++++++++++++++++++++--
src/containers/Sidebar/index.jsx | 1 +
src/data/services/LmsApiService.js | 5 +++
4 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/src/components/Sidebar/index.jsx b/src/components/Sidebar/index.jsx
index 3d73d601d3..e32ba84681 100644
--- a/src/components/Sidebar/index.jsx
+++ b/src/components/Sidebar/index.jsx
@@ -1,5 +1,5 @@
import React, {
- useRef, useContext, useEffect, useCallback,
+ useCallback, useContext, useEffect, useRef, useState,
} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
@@ -8,6 +8,7 @@ import {
BookOpen, CreditCard, Description, InsertChartOutlined, MoneyOutline, Settings, Support, Tag, TrendingUp,
} from '@edx/paragon/icons';
+import { logError } from '@edx/frontend-platform/logging';
import { getConfig } from '@edx/frontend-platform/config';
import IconLink from './IconLink';
@@ -18,6 +19,7 @@ import { TOUR_TARGETS } from '../ProductTours/constants';
import { useOnMount } from '../../hooks';
import { EnterpriseSubsidiesContext } from '../EnterpriseSubsidiesContext';
import { EnterpriseAppContext } from '../EnterpriseApp/EnterpriseAppContextProvider';
+import LmsApiService from '../../data/services/LmsApiService';
const Sidebar = ({
baseUrl,
@@ -31,6 +33,7 @@ const Sidebar = ({
enableAnalyticsScreen,
onWidthChange,
isMobile,
+ enterpriseGroupsV1,
}) => {
const navRef = useRef();
const widthRef = useRef();
@@ -38,6 +41,8 @@ const Sidebar = ({
const { subsidyRequestsCounts } = useContext(SubsidyRequestsContext);
const { canManageLearnerCredit } = useContext(EnterpriseSubsidiesContext);
const { FEATURE_CONTENT_HIGHLIGHTS } = getConfig();
+ const [isSubGroup, setIsSubGroup] = useState(false);
+ const hideHighlightsForGroups = enterpriseGroupsV1 && isSubGroup;
const getSidebarWidth = useCallback(() => {
if (navRef && navRef.current) {
@@ -54,6 +59,23 @@ const Sidebar = ({
widthRef.current = sideBarWidth;
onWidthChange(sideBarWidth);
}
+ async function fetchGroupsData() {
+ try {
+ const response = await LmsApiService.fetchEnterpriseGroup();
+ // we only want to hide the feature if a customer has a group this does not
+ // apply to all contexts/include all users
+ response.data.results.forEach((group) => {
+ if (group.applies_to_all_contexts === false) {
+ setIsSubGroup(true);
+ }
+ });
+ } catch (error) {
+ logError(error);
+ }
+ }
+ if (enterpriseGroupsV1) {
+ fetchGroupsData();
+ }
});
useEffect(() => {
@@ -104,7 +126,7 @@ const Sidebar = ({
id: TOUR_TARGETS.CONTENT_HIGHLIGHTS,
to: `${baseUrl}/admin/${ROUTE_NAMES.contentHighlights}`,
icon: ,
- hidden: !FEATURE_CONTENT_HIGHLIGHTS || !enterpriseCuration?.isHighlightFeatureActive,
+ hidden: !FEATURE_CONTENT_HIGHLIGHTS || !enterpriseCuration?.isHighlightFeatureActive || hideHighlightsForGroups,
notification: isNewArchivedContent,
},
{
@@ -187,6 +209,7 @@ Sidebar.defaultProps = {
enableAnalyticsScreen: false,
onWidthChange: () => {},
isMobile: false,
+ enterpriseGroupsV1: false,
};
Sidebar.propTypes = {
@@ -201,6 +224,7 @@ Sidebar.propTypes = {
enableAnalyticsScreen: PropTypes.bool,
onWidthChange: PropTypes.func,
isMobile: PropTypes.bool,
+ enterpriseGroupsV1: PropTypes.bool,
};
export default Sidebar;
diff --git a/src/containers/Sidebar/Sidebar.test.jsx b/src/containers/Sidebar/Sidebar.test.jsx
index 821b758430..f5334ab4c3 100644
--- a/src/containers/Sidebar/Sidebar.test.jsx
+++ b/src/containers/Sidebar/Sidebar.test.jsx
@@ -1,6 +1,5 @@
/* eslint-disable react/prop-types */
import React from 'react';
-import { getConfig } from '@edx/frontend-platform/config';
import PropTypes from 'prop-types';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
@@ -12,12 +11,13 @@ import {
render, screen,
} from '@testing-library/react';
import '@testing-library/jest-dom';
+import { getConfig } from '@edx/frontend-platform/config';
import Sidebar from './index';
import { SubsidyRequestsContext } from '../../components/subsidy-requests';
import { EnterpriseSubsidiesContext } from '../../components/EnterpriseSubsidiesContext';
import { EnterpriseAppContext } from '../../components/EnterpriseApp/EnterpriseAppContextProvider';
-
+import LmsApiService from '../../data/services/LmsApiService';
import { features } from '../../config';
import {
@@ -34,6 +34,8 @@ jest.mock('@edx/frontend-platform/config', () => ({
})),
}));
+jest.mock('../../data/services/LmsApiService');
+
const mockStore = configureMockStore([thunk]);
const initialState = {
sidebar: {
@@ -46,6 +48,9 @@ const initialState = {
enableSubscriptionManagementScreen: true,
enableAnalyticsScreen: true,
enableReportingConfigScreenLink: true,
+ enterpriseFeatures: {
+ enterpriseGroupsV1: false,
+ },
},
};
@@ -127,6 +132,9 @@ describe('', () => {
},
portalConfiguration: {
enableCodeManagementScreen: false,
+ enterpriseFeatures: {
+ enterpriseGroupsV1: false,
+ },
},
});
@@ -421,6 +429,35 @@ describe('', () => {
}
});
+ it('hides highlights when we have groups with a subset of all learners', async () => {
+ getConfig.mockReturnValue({ FEATURE_CONTENT_HIGHLIGHTS: true });
+ const store = mockStore({
+ ...initialState,
+ portalConfiguration: {
+ enterpriseFeatures: {
+ enterpriseGroupsV1: true,
+ },
+ },
+ });
+
+ LmsApiService.fetchEnterpriseGroup.mockImplementation(() => Promise.resolve({
+ data: { results: [{ applies_to_all_contexts: false }] },
+ }));
+ render();
+ const highlightsLink = expect(screen.queryByRole('link', { name: 'Highlights' }));
+ // we have to wait for the async call to set the state
+ setTimeout(() => {
+ expect(highlightsLink).not.toBeInTheDocument();
+ }, 1000);
+
+ LmsApiService.fetchEnterpriseGroup.mockImplementation(() => Promise.resolve({
+ data: { results: [{ applies_to_all_contexts: true }] },
+ }));
+ render();
+ setTimeout(() => {
+ expect(highlightsLink).toBeInTheDocument();
+ }, 1000);
+ });
describe('notifications', () => {
it('displays notification bubble when there are outstanding license requests', () => {
const contextValue = { subsidyRequestsCounts: { subscriptionLicenses: 2 } };
diff --git a/src/containers/Sidebar/index.jsx b/src/containers/Sidebar/index.jsx
index 27b36abaa4..c0cfa096f6 100644
--- a/src/containers/Sidebar/index.jsx
+++ b/src/containers/Sidebar/index.jsx
@@ -17,6 +17,7 @@ const mapStateToProps = state => ({
enableLearnerPortal: state.portalConfiguration.enableLearnerPortal,
enableLmsConfigurationsScreen: state.portalConfiguration.enableLmsConfigurationsScreen,
enableAnalyticsScreen: state.portalConfiguration.enableAnalyticsScreen,
+ enterpriseGroupsV1: state.portalConfiguration.enterpriseFeatures?.enterpriseGroupsV1,
});
const mapDispatchToProps = dispatch => ({
diff --git a/src/data/services/LmsApiService.js b/src/data/services/LmsApiService.js
index 686164ec4e..ae1059c918 100644
--- a/src/data/services/LmsApiService.js
+++ b/src/data/services/LmsApiService.js
@@ -420,6 +420,11 @@ class LmsApiService {
return response;
};
+ static fetchEnterpriseGroup = async () => {
+ const url = `${LmsApiService.enterpriseGroupUrl}`;
+ return LmsApiService.apiClient().get(url);
+ };
+
static inviteEnterpriseLearnersToGroup = async (groupUuid, formData) => {
const assignLearnerEndpoint = `${LmsApiService.enterpriseGroupUrl}${groupUuid}/assign_learners/`;
return LmsApiService.apiClient().post(assignLearnerEndpoint, formData);