Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Instructed PL Sections to My PL page #57947

Merged
merged 32 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4d89283
set up framework
TurnerRiley Apr 10, 2024
d0a2172
attempt to pull in section data
TurnerRiley Apr 10, 2024
233e5cb
add skip link to self-paced section on LandingPage.jsx
kelbyhawn Apr 11, 2024
4139dfc
add updated PL section to TeacherHomepage.jsx
kelbyhawn Apr 11, 2024
e9b1319
update comment
kelbyhawn Apr 11, 2024
c51e2a6
update icon
kelbyhawn Apr 11, 2024
f7265a8
add unit test to TeacherHomepageTest.js
kelbyhawn Apr 11, 2024
e34e4f7
Merge branch 'staging' into remove-recent-courses-component-from-teac…
kelbyhawn Apr 11, 2024
e2370c0
replace div tag with section tag to fix spacing on online pl courses
kelbyhawn Apr 11, 2024
b018d2f
fix redux to get sections
TurnerRiley Apr 11, 2024
fe40bf5
update strings to reflect kelbys skip link style on my pl page
TurnerRiley Apr 11, 2024
f1ea23e
Merge branch 'staging' into remove-recent-courses-component-from-teac…
kelbyhawn Apr 11, 2024
3218519
merge in kelbys strings
TurnerRiley Apr 12, 2024
7b5f8c5
remove unnecessary changes
TurnerRiley Apr 12, 2024
1ba0841
setup strings on teacher dashboard
TurnerRiley Apr 12, 2024
e65709f
increase permission access
TurnerRiley Apr 12, 2024
4b53719
redux get coteacherInvite
TurnerRiley Apr 12, 2024
aa48e09
add Create Section component
TurnerRiley Apr 12, 2024
c77c227
merge in staging
TurnerRiley Apr 15, 2024
d8d8ef0
set up new component and fix styles for pl sections table
TurnerRiley Apr 15, 2024
4a67a02
add instructors tab
TurnerRiley Apr 15, 2024
44f58ff
update storybook and participant type column formatter
TurnerRiley Apr 15, 2024
e64f892
fix weird spacing for sections
TurnerRiley Apr 15, 2024
284048d
remove blank lines
TurnerRiley Apr 15, 2024
dbb985e
remove banner margin bottom inline style
TurnerRiley Apr 16, 2024
4c90cc0
update strings to match Figma
TurnerRiley Apr 16, 2024
dd279b0
add unit tests for showing right tabs
TurnerRiley Apr 16, 2024
eeb0ad8
remove pl specific tests on TeacherSections since we no longer render…
TurnerRiley Apr 16, 2024
2ef1f39
Merge branch 'staging' into setup-pl-sections-on-my-pl
TurnerRiley Apr 16, 2024
fc02ae4
update ui test behaviors
TurnerRiley Apr 16, 2024
e24fcb1
remove unused parameter
TurnerRiley Apr 17, 2024
1ee8e3b
merge in staging
TurnerRiley Apr 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 8 additions & 5 deletions apps/i18n/common/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,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 @@ -1769,6 +1771,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 @@ -1933,13 +1936,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 @@ -1956,6 +1958,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) && (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The facilitator tab should have more components at some point. While adding those components is outside the scope of this PR, it might be worth separating out this logic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes for sure, my plan once we started implementing more components was to simplify the logic to a series of {shouldRenderXComponent && (<XComponent/>)} where shouldRenderXComponent would contain the logic of checking if the user has the right permissions and any other qualifications

<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