Loading frontend/src/email/EmailForm/InstructorEmailForm.tsx +1 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,7 @@ const InstructorEmailForm: FC<InstructorEmailFormProps> = ({ setActivateMilestone={setActivateMilestone} deactivateMilestone={deactivateMilestone} setDeactivateMilestone={setDeactivateMilestone} template={template} /> <ContentArea content={content} setContent={setContent} /> Loading frontend/src/instructor/MilestoneSelector/MilestoneSelector.tsx +40 −26 Original line number Diff line number Diff line Loading @@ -7,12 +7,27 @@ import { memo, useEffect, useState } from 'react' import notEmpty from '@inject/shared/utils/notEmpty' import { useGetTeamMilestones } from '@inject/graphql/queries/GetTeamMilestones.generated' import { MilestoneState } from '@inject/graphql/fragments/MilestoneState.generated' import { EmailTemplate } from '@inject/graphql/fragments/EmailTemplate.generated' export interface MilestoneOption { milestoneState: MilestoneState selected: boolean } const milestoneOptionsToString = ( milestoneOptions: MilestoneOption[], reached: boolean ) => milestoneOptions .filter(milestoneOption => milestoneOption.selected) .filter(milestoneOption => reached ? milestoneOption.milestoneState.reached : !milestoneOption.milestoneState.reached ) .map(milestoneOption => milestoneOption.milestoneState.milestone.name) .join(' ') const getMilestoneOptionText = (milestoneOption: MilestoneOption) => milestoneOption.milestoneState.reached ? `not ${milestoneOption.milestoneState.milestone.name}` Loading Loading @@ -52,6 +67,7 @@ interface MilestoneSelectorProps { deactivateMilestone: string setActivateMilestone: React.Dispatch<SetStateAction<string>> setDeactivateMilestone: React.Dispatch<SetStateAction<string>> template?: EmailTemplate } const MilestoneSelector = ({ Loading @@ -60,6 +76,7 @@ const MilestoneSelector = ({ deactivateMilestone, setActivateMilestone, setDeactivateMilestone, template, }: MilestoneSelectorProps) => { const { data } = useGetTeamMilestones({ fetchPolicy: 'cache-only', Loading Loading @@ -92,25 +109,13 @@ const MilestoneSelector = ({ )), })) ) }, [activateMilestone, deactivateMilestone]) // eslint-disable-next-line react-hooks/exhaustive-deps }, [template]) const milestoneOptionsToString = (reached: boolean) => milestoneOptions .filter(milestoneOption => milestoneOption.selected) .filter(milestoneOption => reached ? milestoneOption.milestoneState.reached : !milestoneOption.milestoneState.reached ) .map(milestoneOption => milestoneOption.milestoneState.milestone.name) .join(' ') useEffect(() => { setActivateMilestone(milestoneOptionsToString(false)) setDeactivateMilestone(milestoneOptionsToString(true)) // TODO: not ideal, triggers the preceding useEffect }, [milestoneOptions]) const updateActivateMilestone = (milestoneOptions: MilestoneOption[]) => { setActivateMilestone(milestoneOptionsToString(milestoneOptions, false)) setDeactivateMilestone(milestoneOptionsToString(milestoneOptions, true)) } const handleItemChange = ( milestoneOption: MilestoneOption, Loading @@ -118,11 +123,15 @@ const MilestoneSelector = ({ ) => { const index = milestoneOptions.indexOf(milestoneOption) setMilestoneOptions(prev => [ setMilestoneOptions(prev => { const newMilestoneOptions = [ ...prev.slice(0, index), { ...prev[index], selected }, ...prev.slice(index + 1), ]) ] updateActivateMilestone(newMilestoneOptions) return newMilestoneOptions }) } return ( Loading Loading @@ -160,9 +169,14 @@ const MilestoneSelector = ({ } resetOnSelect onClear={() => { setMilestoneOptions(prev => prev.map(milestoneOption => ({ ...milestoneOption, selected: false })) ) setMilestoneOptions(prev => { const newMilestoneOptions = prev.map(milestoneOption => ({ ...milestoneOption, selected: false, })) updateActivateMilestone(newMilestoneOptions) return newMilestoneOptions }) }} menuProps={{ 'aria-label': 'milestones', Loading Loading
frontend/src/email/EmailForm/InstructorEmailForm.tsx +1 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,7 @@ const InstructorEmailForm: FC<InstructorEmailFormProps> = ({ setActivateMilestone={setActivateMilestone} deactivateMilestone={deactivateMilestone} setDeactivateMilestone={setDeactivateMilestone} template={template} /> <ContentArea content={content} setContent={setContent} /> Loading
frontend/src/instructor/MilestoneSelector/MilestoneSelector.tsx +40 −26 Original line number Diff line number Diff line Loading @@ -7,12 +7,27 @@ import { memo, useEffect, useState } from 'react' import notEmpty from '@inject/shared/utils/notEmpty' import { useGetTeamMilestones } from '@inject/graphql/queries/GetTeamMilestones.generated' import { MilestoneState } from '@inject/graphql/fragments/MilestoneState.generated' import { EmailTemplate } from '@inject/graphql/fragments/EmailTemplate.generated' export interface MilestoneOption { milestoneState: MilestoneState selected: boolean } const milestoneOptionsToString = ( milestoneOptions: MilestoneOption[], reached: boolean ) => milestoneOptions .filter(milestoneOption => milestoneOption.selected) .filter(milestoneOption => reached ? milestoneOption.milestoneState.reached : !milestoneOption.milestoneState.reached ) .map(milestoneOption => milestoneOption.milestoneState.milestone.name) .join(' ') const getMilestoneOptionText = (milestoneOption: MilestoneOption) => milestoneOption.milestoneState.reached ? `not ${milestoneOption.milestoneState.milestone.name}` Loading Loading @@ -52,6 +67,7 @@ interface MilestoneSelectorProps { deactivateMilestone: string setActivateMilestone: React.Dispatch<SetStateAction<string>> setDeactivateMilestone: React.Dispatch<SetStateAction<string>> template?: EmailTemplate } const MilestoneSelector = ({ Loading @@ -60,6 +76,7 @@ const MilestoneSelector = ({ deactivateMilestone, setActivateMilestone, setDeactivateMilestone, template, }: MilestoneSelectorProps) => { const { data } = useGetTeamMilestones({ fetchPolicy: 'cache-only', Loading Loading @@ -92,25 +109,13 @@ const MilestoneSelector = ({ )), })) ) }, [activateMilestone, deactivateMilestone]) // eslint-disable-next-line react-hooks/exhaustive-deps }, [template]) const milestoneOptionsToString = (reached: boolean) => milestoneOptions .filter(milestoneOption => milestoneOption.selected) .filter(milestoneOption => reached ? milestoneOption.milestoneState.reached : !milestoneOption.milestoneState.reached ) .map(milestoneOption => milestoneOption.milestoneState.milestone.name) .join(' ') useEffect(() => { setActivateMilestone(milestoneOptionsToString(false)) setDeactivateMilestone(milestoneOptionsToString(true)) // TODO: not ideal, triggers the preceding useEffect }, [milestoneOptions]) const updateActivateMilestone = (milestoneOptions: MilestoneOption[]) => { setActivateMilestone(milestoneOptionsToString(milestoneOptions, false)) setDeactivateMilestone(milestoneOptionsToString(milestoneOptions, true)) } const handleItemChange = ( milestoneOption: MilestoneOption, Loading @@ -118,11 +123,15 @@ const MilestoneSelector = ({ ) => { const index = milestoneOptions.indexOf(milestoneOption) setMilestoneOptions(prev => [ setMilestoneOptions(prev => { const newMilestoneOptions = [ ...prev.slice(0, index), { ...prev[index], selected }, ...prev.slice(index + 1), ]) ] updateActivateMilestone(newMilestoneOptions) return newMilestoneOptions }) } return ( Loading Loading @@ -160,9 +169,14 @@ const MilestoneSelector = ({ } resetOnSelect onClear={() => { setMilestoneOptions(prev => prev.map(milestoneOption => ({ ...milestoneOption, selected: false })) ) setMilestoneOptions(prev => { const newMilestoneOptions = prev.map(milestoneOption => ({ ...milestoneOption, selected: false, })) updateActivateMilestone(newMilestoneOptions) return newMilestoneOptions }) }} menuProps={{ 'aria-label': 'milestones', Loading