Skip to content

Commit

Permalink
Move Instructed PL Sections to My PL page (#57947)
Browse files Browse the repository at this point in the history
* set up framework

* attempt to pull in section data

* add skip link to self-paced section on LandingPage.jsx

* add updated PL section to TeacherHomepage.jsx

* update comment

* update icon

* add unit test to TeacherHomepageTest.js

* replace div tag with section tag to fix spacing on online pl courses

* fix redux to get sections

* update strings to reflect kelbys skip link style on my pl page

* remove unnecessary changes

* setup strings on teacher dashboard

* increase permission access

* redux get coteacherInvite

* add Create Section component

* set up new component and fix styles for pl sections table

* add instructors tab

* update storybook and participant type column formatter

* fix weird spacing for sections

* remove blank lines

* remove banner margin bottom inline style

* update strings to match Figma

* add unit tests for showing right tabs

* remove pl specific tests on TeacherSections since we no longer render there

* update ui test behaviors

* remove unused parameter

---------

Co-authored-by: Kelby Hawn <9256643+kelbyhawn@users.noreply.github.com>
  • Loading branch information
TurnerRiley and kelbyhawn committed Apr 17, 2024
1 parent 1edba41 commit 771e1ea
Show file tree
Hide file tree
Showing 13 changed files with 749 additions and 179 deletions.
13 changes: 8 additions & 5 deletions apps/i18n/common/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1752,6 +1752,8 @@
"myProfessionalLearningCourses": "My Professional Learning Courses",
"myProfessionalLearningCoursesHomepageDesc": "You can now see the professional learning courses you've started or completed on the Professional Learning page.",
"myProfessionalLearningCoursesHomepageButton": "View my Professional Learning courses",
"myProfessionalLearningSectionsHomepageDesc": "Your instructor professional learning sections have moved! Find them on the My Professional Learning page.",
"myProfessionalLearningSectionsHomepageButton": "View my Professional Learning sections",
"name": "Name",
"nameRequired": "Student name (required)",
"nameFailureDialogTitle": "Unable to rename project",
Expand All @@ -1771,6 +1773,7 @@
"newSectionAdd": "Add a new classroom section",
"newSectionCreate": "Create a new section",
"newSectionPlAdd": "Add a new professional learning section",
"newSectionMyPlAdd": "Create a new professional section to start managing professional learning.",
"next": "Next",
"nextLevel": "Congratulations! You completed Puzzle {puzzleNumber}.",
"nextLevelLink": "Next level",
Expand Down Expand Up @@ -1935,13 +1938,12 @@
"playzoneProjectsTitle": "Open a Project",
"playzoneSecondaryHeader": "Ask your teacher what to do next",
"plLandingDescription": "Thank you for completing a {course} workshop. Please complete this survey about your experience to help us improve future professional development workshops!",
"plLandingHeading": "My Professional Learning",
"plLandingSubheading": "Submit your feedback",
"plLandingStartSurvey": "Start survey",
"plLandingTabFacilitatorCenter": "My Facilitator Center",
"plLandingTabRPCenter": "My Regional Partner Center",
"plLandingTabWorkshopOrganizerCenter": "My Workshop Organizer Center",
"plLandingTabInstructorCenter": "My Instructor Center",
"plLandingTabFacilitatorCenter": "Facilitator Center",
"plLandingTabRPCenter": "Regional Partner Center",
"plLandingTabWorkshopOrganizerCenter": "Workshop Organizer Center",
"plLandingTabInstructors": "Instructors",
"plLandingSelfPacedProgressHeading": "Self-Paced Professional Learning Courses",
"plLandingGettingStartedHeading": "Getting started with Professional Learning",
"plLandingGettingStartedSubHeading": "Code.org Professional Learning",
Expand All @@ -1958,6 +1960,7 @@
"plLandingStaticPLSelfPacedButton": "Start professional learning courses",
"plSectionsJoined": "Professional Learning Sections I've Joined",
"plSectionsTitle": "Professional Learning Sections",
"plSectionsInstructorTitle": "Instructor Professional Learning Sections",
"plugged": "Plugged",
"pluggedLessonsNote": "*Online or ‘plugged’ lessons are automatically marked as complete on your behalf once 80% of your class has completed 60% of the available lesson.",
"picturePassword": "Picture password",
Expand Down
161 changes: 109 additions & 52 deletions apps/src/code-studio/pd/professional_learning_landing/LandingPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// studio.code.org/my-professional-learning

import PropTypes from 'prop-types';
import React from 'react';
import React, {useEffect, useState} from 'react';
import {connect, useDispatch} from 'react-redux';
import i18n from '@cdo/locale';
import {pegasus} from '@cdo/apps/lib/util/urlHelpers';
import {Heading2} from '@cdo/apps/componentLibrary/typography';
Expand All @@ -12,55 +13,86 @@ import SelfPacedProgressTable from './SelfPacedProgressTable';
import HeaderBannerNoImage from '@cdo/apps/templates/HeaderBannerNoImage';
import TwoColumnActionBlock from '@cdo/apps/templates/studioHomepages/TwoColumnActionBlock';
import ActionBlocksWrapper from '@cdo/apps/templates/studioHomepages/ActionBlocksWrapper';
import CoteacherInviteNotification from '@cdo/apps/templates/studioHomepages/CoteacherInviteNotification';
import OwnedSections from '@cdo/apps/templates/teacherDashboard/OwnedSections';
import SetUpSections from '@cdo/apps/templates/studioHomepages/SetUpSections';
import AddSectionDialog from '@cdo/apps/templates/teacherDashboard/AddSectionDialog';
import style from './landingPage.module.scss';
import './tableStyles.scss';
import Tabs from '@cdo/apps/componentLibrary/tabs';
import {
asyncLoadSectionData,
asyncLoadCoteacherInvite,
hiddenPlSectionIds,
} from '@cdo/apps/templates/teacherDashboard/teacherSectionsRedux';

const getAvailableTabs = () => {
// [TODO]: return a subset of the tabs below based on the user's permission level
return [
const getAvailableTabs = permissions => {
let tabs = [
{
value: 'myPL',
text: i18n.plLandingHeading(),
text: i18n.professionalLearning(),
},
// {
// value: 'myFacilitatorCenter',
// text: i18n.plLandingTabFacilitatorCenter(),
// },
// {
// value: 'myRPCenter',
// text: i18n.plLandingTabRPCenter(),
// },
// {
// value: 'myWorkshopOrganizerCenter',
// text: i18n.plLandingTabWorkshopOrganizerCenter(),
// },
// {
// value: 'myInstructorCenter',
// text: i18n.plLandingTabInstructorCenter(),
// },
];

if (permissions.includes('facilitator')) {
tabs.push({
value: 'myFacilitatorCenter',
text: i18n.plLandingTabFacilitatorCenter(),
});
}

if (
permissions.includes('universal_instructor') ||
permissions.includes('plc_reviewer')
) {
tabs.push({
value: 'instructors',
text: i18n.plLandingTabInstructors(),
});
}

// {
// value: 'myRPCenter',
// text: i18n.plLandingTabRPCenter(),
// },
// {
// value: 'myWorkshopOrganizerCenter',
// text: i18n.plLandingTabWorkshopOrganizerCenter(),
// },

return tabs;
};

export default function LandingPage({
function LandingPage({
lastWorkshopSurveyUrl,
lastWorkshopSurveyCourse,
deeperLearningCourseData,
currentYearApplicationId,
workshopsAsParticipant,
plCoursesStarted,
userPermissions,
plSectionIds,
hiddenPlSectionIds,
}) {
const availableTabs = getAvailableTabs();
const availableTabs = getAvailableTabs(userPermissions);
const [currentTab, setCurrentTab] = useState(availableTabs[0].value);
const headerContainerStyles =
availableTabs.length > 1 ? '' : style.headerWithoutTabsContainer;
// [TODO]: Uncomment this out once currentTab will affect what content is showed.
// const [currentTab, setCurrentTab] = useState(availableTabs[0].value);
availableTabs.length > 1
? style.headerWithTabsContainer
: style.headerWithoutTabsContainer;

const showGettingStartedBanner =
!currentYearApplicationId &&
workshopsAsParticipant?.length === 0 &&
plCoursesStarted?.length === 0;

// Load PL section info into redux
const dispatch = useDispatch();
useEffect(() => {
dispatch(asyncLoadSectionData());
dispatch(asyncLoadCoteacherInvite());
}, [dispatch]);

const RenderGettingStartedBanner = () => (
<TwoColumnActionBlock
imageUrl={pegasus(
Expand All @@ -75,7 +107,6 @@ export default function LandingPage({
text: i18n.plLandingGettingStartedButton(),
},
]}
marginBottom={'0'}
/>
);

Expand Down Expand Up @@ -142,52 +173,78 @@ export default function LandingPage({
name="myPLTabs"
tabs={availableTabs}
defaultSelectedTabValue={availableTabs[0].value}
onChange={tab => {
// [TODO]: Uncomment this out once
// currentTab affects what content
// is shown.
//setCurrentTab(tab);
console.log(tab);
}}
onChange={tab => setCurrentTab(tab)}
/>
</nav>
)}
</HeaderBannerNoImage>
</div>
<main className={style.wrapper}>
{showGettingStartedBanner && RenderGettingStartedBanner()}
{lastWorkshopSurveyUrl && RenderLastWorkshopSurveyBanner()}
{plCoursesStarted?.length >= 1 && (
<section id={'self-paced-pl'}>
<Heading2>{i18n.plLandingSelfPacedProgressHeading()}</Heading2>
{RenderSelfPacedProgressTable()}
</section>
{currentTab === 'myPL' && (
<>
{showGettingStartedBanner && RenderGettingStartedBanner()}
{lastWorkshopSurveyUrl && RenderLastWorkshopSurveyBanner()}
{plCoursesStarted?.length >= 1 && (
<section id={'self-paced-pl'}>
<Heading2>{i18n.plLandingSelfPacedProgressHeading()}</Heading2>
{RenderSelfPacedProgressTable()}
</section>
)}
<section>
<EnrolledWorkshops />
</section>
{deeperLearningCourseData?.length >= 1 && (
<section>
<Heading2>Online Professional Learning Courses</Heading2>
<ProfessionalLearningCourseProgress
deeperLearningCourseData={deeperLearningCourseData}
/>
</section>
)}
<section>
<Heading2>{i18n.plLandingRecommendedHeading()}</Heading2>
{RenderStaticRecommendedPL()}
</section>
</>
)}
<section>
<EnrolledWorkshops />
</section>
{deeperLearningCourseData?.length >= 1 && (
{['myFacilitatorCenter', 'instructors'].includes(currentTab) && (
<section>
<Heading2>Online Professional Learning Courses</Heading2>
<ProfessionalLearningCourseProgress
deeperLearningCourseData={deeperLearningCourseData}
<Heading2>{i18n.plSectionsInstructorTitle()}</Heading2>
<SetUpSections
headingText={i18n.newSectionCreate()}
descriptionText={i18n.newSectionMyPlAdd()}
solidBorder={true}
/>
<CoteacherInviteNotification isForPl={true} />
<OwnedSections
isPlSections={true}
sectionIds={plSectionIds}
hiddenSectionIds={hiddenPlSectionIds}
/>
<AddSectionDialog />
</section>
)}
<section>
<Heading2>{i18n.plLandingRecommendedHeading()}</Heading2>
{RenderStaticRecommendedPL()}
</section>
</main>
</>
);
}

export const UnconnectedLandingPage = LandingPage;

export default connect(state => ({
plSectionIds: state.teacherSections.plSectionIds,
hiddenPlSectionIds: hiddenPlSectionIds(state),
}))(LandingPage);

LandingPage.propTypes = {
lastWorkshopSurveyUrl: PropTypes.string,
lastWorkshopSurveyCourse: PropTypes.string,
deeperLearningCourseData: PropTypes.array,
currentYearApplicationId: PropTypes.number,
workshopsAsParticipant: PropTypes.array,
plCoursesInstructed: PropTypes.array,
plCoursesStarted: PropTypes.array,
userPermissions: PropTypes.arrayOf(PropTypes.string),
plSectionIds: PropTypes.arrayOf(PropTypes.number),
hiddenPlSectionIds: PropTypes.arrayOf(PropTypes.number),
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ main.wrapper {
}

section {
padding: 4rem 0 0 !important;
padding: 0 0 4rem;
}

.headerContainer {
Expand All @@ -19,7 +19,15 @@ section {
}

.headerWithoutTabsContainer {
padding-bottom: 4rem;
section {
padding: 4rem 0 4rem !important;
}
}

.headerWithTabsContainer {
section {
padding: 4rem 0 0 !important;
}
}

.myPlTabsContainer {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
import LandingPage from '@cdo/apps/code-studio/pd/professional_learning_landing/LandingPage';
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {getStore} from '@cdo/apps/redux';
import analyticsReporter from '@cdo/apps/lib/util/AnalyticsReporter';
import getScriptData from '@cdo/apps/util/getScriptData';
import {EVENTS} from '@cdo/apps/lib/util/AnalyticsConstants';

// Execute after page has fully loaded so the Amplitude event only fires on full page load
$(() => {
const store = getStore();

analyticsReporter.sendEvent(EVENTS.MY_PL_PAGE_VISITED);

const landingPageData = getScriptData('landingPageData');

ReactDOM.render(
<LandingPage
lastWorkshopSurveyUrl={landingPageData['last_workshop_survey_url']}
lastWorkshopSurveyCourse={landingPageData['last_workshop_survey_course']}
deeperLearningCourseData={landingPageData['summarized_plc_enrollments']}
currentYearApplicationId={landingPageData['current_year_application_id']}
workshopsAsParticipant={landingPageData['workshops_as_participant']}
plCoursesStarted={landingPageData['pl_courses_started']}
/>,
<Provider store={store}>
<LandingPage
lastWorkshopSurveyUrl={landingPageData['last_workshop_survey_url']}
lastWorkshopSurveyCourse={
landingPageData['last_workshop_survey_course']
}
deeperLearningCourseData={landingPageData['summarized_plc_enrollments']}
currentYearApplicationId={
landingPageData['current_year_application_id']
}
workshopsAsParticipant={landingPageData['workshops_as_participant']}
plCoursesStarted={landingPageData['pl_courses_started']}
userPermissions={landingPageData['user_permissions']}
/>
</Provider>,
document.getElementById('pl-landing-page-container')
);
});
10 changes: 8 additions & 2 deletions apps/src/templates/studioHomepages/SetUpSections.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const STARTED_EVENT = 'Section Setup Started';
class SetUpSections extends Component {
static propTypes = {
beginEditingSection: PropTypes.func.isRequired,
headingText: PropTypes.string,
descriptionText: PropTypes.string,
solidBorder: PropTypes.bool,
};

// Wrapped to avoid passing event args
Expand All @@ -31,12 +34,15 @@ class SetUpSections extends Component {
return (
<BorderedCallToAction
type="sections"
headingText={i18n.newSectionAdd()}
descriptionText={i18n.createNewClassroom()}
headingText={this.props.headingText || i18n.newSectionAdd()}
descriptionText={
this.props.descriptionText || i18n.createNewClassroom()
}
buttonText={i18n.createSection()}
className="uitest-set-up-sections"
buttonClass="uitest-newsection"
onClick={this.beginEditingSection}
solidBorder={this.props.solidBorder || false}
/>
);
}
Expand Down

0 comments on commit 771e1ea

Please sign in to comment.