Compare commits

..

3 Commits

Author SHA1 Message Date
lunyachek
fbaa41a8ae feat: Add border for active tab in course navigation at Live page 2023-03-22 10:37:01 -04:00
ihor-romaniuk
5dab08761c fix: fix alignment in the streak celebration modal 2023-03-01 10:01:18 -05:00
Eugene Dyudyunov
e499280e49 fix: first section celebration
Fix the first section celebration modal showing logic.

On Nutmeg+ it's shown only after the page reload or after going directly
to the second section from the course home. Going through the course
with the Next/Previous buttons has no effect (which worked on Maple).

Notes:
- the weekly goal has the same showing logic, but I assume that is
correct behavior so no changes are added for it in this commit.
- showing a celebration modal for the first section completion when
going directly to the first unit of the second section seems to be a bug
(reproduces on Maple too)
2023-02-15 11:49:04 -05:00
7 changed files with 52 additions and 11 deletions

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
import { useDispatch } from 'react-redux';
@@ -46,10 +46,8 @@ function Course({
// Below the tabs, above the breadcrumbs alerts (appearing in the order listed here)
const dispatch = useDispatch();
const celebrateFirstSection = celebrations && celebrations.firstSection;
const [firstSectionCelebrationOpen, setFirstSectionCelebrationOpen] = useState(shouldCelebrateOnSectionLoad(
courseId, sequenceId, celebrateFirstSection, dispatch, celebrations,
));
const [firstSectionCelebrationOpen, setFirstSectionCelebrationOpen] = useState(false);
// If streakLengthToCelebrate is populated, that modal takes precedence. Wait til the next load to display
// the weekly goal celebration modal.
const [weeklyGoalCelebrationOpen, setWeeklyGoalCelebrationOpen] = useState(
@@ -74,6 +72,17 @@ function Course({
/** [MM-P2P] Experiment */
const MMP2P = initCoursewareMMP2P(courseId, sequenceId, unitId);
useEffect(() => {
const celebrateFirstSection = celebrations && celebrations.firstSection;
setFirstSectionCelebrationOpen(shouldCelebrateOnSectionLoad(
courseId,
sequenceId,
celebrateFirstSection,
dispatch,
celebrations,
));
}, [sequenceId]);
return (
<SidebarProvider courseId={courseId} unitId={unitId}>
<Helmet>

View File

@@ -9,6 +9,7 @@ import {
useWindowSize,
} from '@edx/paragon';
import { useDispatch } from 'react-redux';
import ClapsMobile from './assets/claps_280x201.gif';
import ClapsTablet from './assets/claps_456x328.gif';
import messages from './messages';
@@ -19,12 +20,13 @@ import { useModel } from '../../../generic/model-store';
function CelebrationModal({
courseId, intl, isOpen, onClose, ...rest
}) {
const { org } = useModel('courseHomeMeta', courseId);
const { org, celebrations } = useModel('courseHomeMeta', courseId);
const dispatch = useDispatch();
const wideScreen = useWindowSize().width >= breakpoints.small.minWidth;
useEffect(() => {
if (isOpen) {
recordFirstSectionCelebration(org, courseId);
recordFirstSectionCelebration(org, courseId, celebrations, dispatch);
}
}, [isOpen]);

View File

@@ -15,9 +15,20 @@ function handleNextSectionCelebration(sequenceId, nextSequenceId) {
});
}
function recordFirstSectionCelebration(org, courseId) {
function recordFirstSectionCelebration(org, courseId, celebrations, dispatch) {
// Tell the LMS
postCelebrationComplete(courseId, { first_section: false });
// Update our local copy of course data from LMS
dispatch(updateModel({
modelType: 'courseHomeMeta',
model: {
id: courseId,
celebrations: {
...celebrations,
firstSection: false,
},
},
}));
// Tell our analytics
const { administrator } = getAuthenticatedUser();

View File

@@ -0,0 +1,15 @@
import { recordFirstSectionCelebration } from './utils';
jest.mock('@edx/frontend-platform/analytics');
jest.mock('./data/api');
jest.mock('@edx/frontend-platform/auth', () => ({
getAuthenticatedUser: jest.fn(() => ({ administrator: 'admin' })),
}));
describe('recordFirstSectionCelebration', () => {
it('updates the local copy of the course data from the LMS', async () => {
const dispatchMock = jest.fn();
recordFirstSectionCelebration('org', 'courseId', 'celebration', dispatchMock);
expect(dispatchMock).toHaveBeenCalled();
});
});

View File

@@ -57,7 +57,7 @@ subscribe(APP_READY, () => {
</TabContainer>
</PageRoute>
<PageRoute path="/course/:courseId/live">
<TabContainer tab="live" fetch={fetchLiveTab} slice="courseHome">
<TabContainer tab="lti_live" fetch={fetchLiveTab} slice="courseHome">
<LiveTab />
</TabContainer>
</PageRoute>

View File

@@ -160,8 +160,8 @@ function StreakModal({
</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body className="modal-body">
<p>{intl.formatMessage(messages.streakBody)}</p>
<p className="modal-image">
<p className="text-center">{intl.formatMessage(messages.streakBody)}</p>
<p className="modal-image text-center">
{!wideScreen && <img src={StreakMobileImage} alt="" className="img-fluid" />}
{wideScreen && <img src={StreakDesktopImage} alt="" className="img-fluid" />}
</p>

View File

@@ -26,6 +26,10 @@
.modal-body {
padding-top: .5rem;
font-size: 1.2rem;
.pgn__modal-body-content {
text-align: center;
}
}
.modal-footer {