diff --git a/.env b/.env
index 2291ec6..deb1b16 100644
--- a/.env
+++ b/.env
@@ -41,4 +41,4 @@ ACCOUNT_PROFILE_URL=''
ENABLE_NOTICES=''
CAREER_LINK_URL=''
OPTIMIZELY_FULL_STACK_SDK_KEY=''
-EXPERIMENT_08_23_VAN_PAINTED_DOOR=true
+EXPERIMENT_08_23_VAN_PAINTED_DOOR='true'
diff --git a/.env.development b/.env.development
index 78e4c40..c1a60a8 100644
--- a/.env.development
+++ b/.env.development
@@ -48,3 +48,4 @@ ACCOUNT_PROFILE_URL='http://localhost:1995'
ENABLE_NOTICES=''
CAREER_LINK_URL=''
OPTIMIZELY_FULL_STACK_SDK_KEY=''
+EXPERIMENT_08_23_VAN_PAINTED_DOOR=true
diff --git a/src/containers/CertificatePreviewModal/hooks.js b/src/containers/CertificatePreviewModal/hooks.js
new file mode 100644
index 0000000..6558b22
--- /dev/null
+++ b/src/containers/CertificatePreviewModal/hooks.js
@@ -0,0 +1,29 @@
+import { getConfig } from '@edx/frontend-platform';
+import { useIntl } from '@edx/frontend-platform/i18n';
+
+import { reduxHooks } from 'hooks';
+import messages from './messages';
+
+export const useCertificatePreviewData = () => {
+ const { formatMessage } = useIntl();
+
+ const selectedCardId = reduxHooks.useCertificatePreviewData().cardId;
+
+ const { courseId } = reduxHooks.useCardCourseRunData(selectedCardId) || {};
+
+ const courseTitle = courseId;
+ const header = formatMessage(messages.previewTitle, { courseTitle });
+
+ const closePreviewModal = reduxHooks.useUpdateCertificatePreviewModalCallback(null);
+
+ const getCertificatePreviewUrl = () => `${getConfig().LMS_BASE_URL}/certificates/upsell/course/${courseId}`;
+
+ return {
+ showModal: selectedCardId != null,
+ header,
+ closePreviewModal,
+ getCertificatePreviewUrl,
+ };
+};
+
+export default useCertificatePreviewData;
diff --git a/src/containers/CertificatePreviewModal/index.jsx b/src/containers/CertificatePreviewModal/index.jsx
new file mode 100644
index 0000000..3499c9b
--- /dev/null
+++ b/src/containers/CertificatePreviewModal/index.jsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {
+ ModalDialog,
+} from '@edx/paragon';
+import { UpgradeButton } from '../CourseCard/components/CourseCardActions/UpgradeButton';
+import useCertificatePreviewData from './hooks';
+
+export const CertificatePreviewModal = ({
+ cardId,
+}) => {
+ const {
+ showModal,
+ header,
+ closePreviewModal,
+ getCertificatePreviewUrl,
+ } = useCertificatePreviewData();
+
+ return (
+
+ {header}
+
+
+
+
+
+ );
+};
+CertificatePreviewModal.propTypes = {
+ cardId: PropTypes.string.isRequired,
+};
+
+export default CertificatePreviewModal;
diff --git a/src/containers/CertificatePreviewModal/messages.js b/src/containers/CertificatePreviewModal/messages.js
new file mode 100644
index 0000000..1011a5f
--- /dev/null
+++ b/src/containers/CertificatePreviewModal/messages.js
@@ -0,0 +1,12 @@
+/* eslint-disable quotes */
+import { StrictDict } from 'utils';
+
+export const messages = StrictDict({
+ previewTitle: {
+ id: 'learner-dash.certificatePreview.title',
+ description: 'The title of the email settings modal',
+ defaultMessage: 'Your certificate preview for {courseTitle} ',
+ },
+});
+
+export default messages;
diff --git a/src/containers/CourseCard/components/CourseCardDetails/hooks.js b/src/containers/CourseCard/components/CourseCardDetails/hooks.js
index b7d72c5..f0d8d60 100644
--- a/src/containers/CourseCard/components/CourseCardDetails/hooks.js
+++ b/src/containers/CourseCard/components/CourseCardDetails/hooks.js
@@ -47,6 +47,7 @@ export const useCardDetailsData = ({ cardId }) => {
} = reduxHooks.useCardEntitlementData(cardId);
const openSessionModal = reduxHooks.useUpdateSelectSessionModalCallback(cardId);
+ const openCertificatePreview = reduxHooks.useUpdateCertificatePreviewModalCallback(cardId);
return {
providerName: providerName || formatMessage(messages.unknownProviderName),
@@ -57,6 +58,7 @@ export const useCardDetailsData = ({ cardId }) => {
openSessionModal,
courseNumber,
changeOrLeaveSessionMessage: formatMessage(messages.changeOrLeaveSessionButton),
+ openCertificatePreview,
};
};
diff --git a/src/containers/CourseCard/components/CourseCardDetails/index.jsx b/src/containers/CourseCard/components/CourseCardDetails/index.jsx
index fedc89e..8a26f7c 100644
--- a/src/containers/CourseCard/components/CourseCardDetails/index.jsx
+++ b/src/containers/CourseCard/components/CourseCardDetails/index.jsx
@@ -16,23 +16,35 @@ export const CourseCardDetails = ({ cardId }) => {
openSessionModal,
courseNumber,
changeOrLeaveSessionMessage,
+ openCertificatePreview,
} = useCardDetailsData({ cardId });
return (
-
- {providerName} • {courseNumber}
- {!(isEntitlement && !isFulfilled) && accessMessage && (
- ` • ${accessMessage}`
- )}
- {isEntitlement && isFulfilled && canChange ? (
- <>
- {' • '}
-
- >
- ) : null}
-
+
+
+ {providerName} • {courseNumber}
+ {!(isEntitlement && !isFulfilled) && accessMessage && (
+ ` • ${accessMessage}`
+ )}
+ {isEntitlement && isFulfilled && canChange ? (
+ <>
+ {' • '}
+
+ >
+ ) : null}
+
+
+
);
};
diff --git a/src/containers/CourseCard/components/CourseCardMenu/index.jsx b/src/containers/CourseCard/components/CourseCardMenu/index.jsx
index b9f529c..f92f676 100644
--- a/src/containers/CourseCard/components/CourseCardMenu/index.jsx
+++ b/src/containers/CourseCard/components/CourseCardMenu/index.jsx
@@ -7,6 +7,7 @@ import { MoreVert } from '@edx/paragon/icons';
import { StrictDict } from '@edx/react-unit-test-utils';
import EmailSettingsModal from 'containers/EmailSettingsModal';
+import CertificatePreviewModal from 'containers/CertificatePreviewModal';
import UnenrollConfirmModal from 'containers/UnenrollConfirmModal';
import { reduxHooks } from 'hooks';
import SocialShareMenu from './SocialShareMenu';
@@ -32,6 +33,7 @@ export const CourseCardMenu = ({ cardId }) => {
const { shouldShowUnenrollItem, shouldShowDropdown } = useOptionVisibility(cardId);
const { isMasquerading } = reduxHooks.useMasqueradeData();
const { isEmailEnabled } = reduxHooks.useCardEnrollmentData(cardId);
+ const showCertificatePreviewModal = reduxHooks.useShowCertificatePreviewModal(cardId);
if (!shouldShowDropdown) {
return null;
@@ -73,6 +75,11 @@ export const CourseCardMenu = ({ cardId }) => {
cardId={cardId}
/>
)}
+ {showCertificatePreviewModal && (
+
+ )}
>
);
};
diff --git a/src/containers/WidgetContainers/AppWrapper/index.jsx b/src/containers/WidgetContainers/AppWrapper/index.jsx
index d1e999e..e713440 100644
--- a/src/containers/WidgetContainers/AppWrapper/index.jsx
+++ b/src/containers/WidgetContainers/AppWrapper/index.jsx
@@ -6,14 +6,12 @@ import PaintedDoorExperimentProvider from 'widgets/RecommendationsPaintedDoorBtn
export const AppWrapper = ({
children,
}) => {
- if (process.env.EXPERIMENT_08_23_VAN_PAINTED_DOOR) {
- return (
-
- {children}
-
- );
- }
- return children;
+ console.log(`process.env.EXPERIMENT_08_23_VAN_PAINTED_DOOR = ${Boolean(process.env.EXPERIMENT_08_23_VAN_PAINTED_DOOR)}`);
+ return (
+
+ {children}
+
+ );
};
AppWrapper.propTypes = {
children: PropTypes.oneOfType([
diff --git a/src/data/redux/app/reducer.js b/src/data/redux/app/reducer.js
index a8df1ee..7ffd47d 100644
--- a/src/data/redux/app/reducer.js
+++ b/src/data/redux/app/reducer.js
@@ -12,6 +12,7 @@ const initialState = {
suggestedCourses: [],
filterState: {},
selectSessionModal: {},
+ certificatePreviewModal: {},
};
export const cardId = (val) => `card-${val}`;
@@ -48,6 +49,10 @@ const app = createSlice({
...state,
selectSessionModal: { cardId: payload },
}),
+ updateCertificatePreviewModal: (state, { payload }) => ({
+ ...state,
+ certificatePreviewModal: { cardId: payload },
+ }),
setPageNumber: (state, { payload }) => ({ ...state, pageNumber: payload }),
},
});
diff --git a/src/data/redux/app/selectors/appSelectors.js b/src/data/redux/app/selectors/appSelectors.js
index 04932e1..501d68d 100644
--- a/src/data/redux/app/selectors/appSelectors.js
+++ b/src/data/redux/app/selectors/appSelectors.js
@@ -19,9 +19,15 @@ export const showSelectSessionModal = createSelector(
(data) => data.cardId != null,
);
+export const showCertificatePreviewModal = createSelector(
+ [simpleSelectors.certificatePreviewModal],
+ (data) => data.cardId != null,
+);
+
export default StrictDict({
numCourses,
hasCourses,
hasAvailableDashboards,
showSelectSessionModal,
+ showCertificatePreviewModal,
});
diff --git a/src/data/redux/app/selectors/simpleSelectors.js b/src/data/redux/app/selectors/simpleSelectors.js
index c8ce2a0..e9716e8 100644
--- a/src/data/redux/app/selectors/simpleSelectors.js
+++ b/src/data/redux/app/selectors/simpleSelectors.js
@@ -14,6 +14,7 @@ export const simpleSelectors = StrictDict({
emailConfirmation: mkSimpleSelector(app => app.emailConfirmation),
enterpriseDashboard: mkSimpleSelector(app => app.enterpriseDashboard || {}),
selectSessionModal: mkSimpleSelector(app => app.selectSessionModal),
+ certificatePreviewModal: mkSimpleSelector(app => app.certificatePreviewModal),
pageNumber: mkSimpleSelector(app => app.pageNumber),
socialShareSettings: mkSimpleSelector(app => app.socialShareSettings),
});
diff --git a/src/data/redux/hooks/app.js b/src/data/redux/hooks/app.js
index dd74aa8..ad876fd 100644
--- a/src/data/redux/hooks/app.js
+++ b/src/data/redux/hooks/app.js
@@ -13,6 +13,8 @@ export const useEmailConfirmationData = () => useSelector(selectors.emailConfirm
export const useEnterpriseDashboardData = () => useSelector(selectors.enterpriseDashboard);
export const usePlatformSettingsData = () => useSelector(selectors.platformSettings);
export const useSelectSessionModalData = () => useSelector(selectors.selectSessionModal);
+export const useCertificatePreviewData = () => useSelector(selectors.certificatePreviewModal);
+
export const useSocialShareSettings = () => useSelector(selectors.socialShareSettings);
/** global-level meta-selectors **/
@@ -22,6 +24,7 @@ export const useCurrentCourseList = (opts) => useSelector(
state => selectors.currentList(state, opts),
);
export const useShowSelectSessionModal = () => useSelector(selectors.showSelectSessionModal);
+export const useShowCertificatePreviewModal = () => useSelector(selectors.showCertificatePreviewModal);
// eslint-disable-next-line
export const useCourseCardData = (selector) => (cardId) => useSelector(
@@ -67,6 +70,11 @@ export const useUpdateSelectSessionModalCallback = (cardId) => {
return () => dispatch(actions.updateSelectSessionModal(cardId));
};
+export const useUpdateCertificatePreviewModalCallback = (cardId) => {
+ const dispatch = useDispatch();
+ return () => dispatch(actions.updateCertificatePreviewModal(cardId));
+};
+
export const useTrackCourseEvent = (tracker, cardId, ...args) => {
const { courseId } = module.useCardCourseRunData(cardId);
return (e) => tracker(courseId, ...args)(e);