Restore navigation flow when closing the pace modal
Fix focus loss when closing the pace modal, restoring the focus to the element that opened the modal closes LS-3625 flag=course_paces_redesign Test plan: - Go to the course pace landing page - Open the default course pace modal - Do some stuff and close it - Expect the focus to come back to the Edit default pace button - Repeat the process for section and student paces - Make sure the focus gets restored when closing the modal using the X , the Close button, or the Discard Changes button when attempting to close the modal without saving Change-Id: Ie3ee9374afecf813433495c1ef0fa313f8c4ec96 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/306475 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Jackson Howe <jackson.howe@instructure.com> QA-Review: Jackson Howe <jackson.howe@instructure.com> Product-Review: Jonathan Guardado <jonathan.guardado@instructure.com>
This commit is contained in:
parent
613f951bd6
commit
4c02449058
|
@ -39,6 +39,7 @@ import {getCoursePace, isNewPace} from '../../reducers/course_paces'
|
|||
import {PaceContext, CoursePace, StoreState, ResponsiveSizes} from '../../types'
|
||||
import {actions} from '../../actions/ui'
|
||||
import {paceContextsActions} from '../../actions/pace_contexts'
|
||||
import {generateModalLauncherId} from '../../utils/utils'
|
||||
|
||||
const I18n = useI18nScope('course_paces_header')
|
||||
|
||||
|
@ -181,6 +182,10 @@ export const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
|||
margin={props.responsiveSize === 'large' ? '0' : 'small 0 0'}
|
||||
>
|
||||
<Link
|
||||
id={generateModalLauncherId({
|
||||
type: 'Course',
|
||||
item_id: window.ENV.COURSE_ID,
|
||||
} as PaceContext)}
|
||||
isWithinText={false}
|
||||
data-testid="go-to-default-pace"
|
||||
onClick={() => {
|
||||
|
|
|
@ -36,6 +36,7 @@ import {Spinner} from '@instructure/ui-spinner'
|
|||
import Paginator from '@canvas/instui-bindings/react/Paginator'
|
||||
import {formatTimeAgoDate} from '../utils/date_stuff/date_helpers'
|
||||
import {paceContextsActions} from '../actions/pace_contexts'
|
||||
import {generateModalLauncherId} from '../utils/utils'
|
||||
|
||||
const I18n = useI18nScope('course_paces_app')
|
||||
|
||||
|
@ -143,7 +144,11 @@ const PaceContextsTable = ({
|
|||
}
|
||||
|
||||
const renderContextLink = (paceContext: PaceContext) => (
|
||||
<Link isWithinText={false} onClick={() => handleContextSelect(paceContext)}>
|
||||
<Link
|
||||
id={generateModalLauncherId(paceContext)}
|
||||
isWithinText={false}
|
||||
onClick={() => handleContextSelect(paceContext)}
|
||||
>
|
||||
<TruncateText>{paceContext.name}</TruncateText>
|
||||
</Link>
|
||||
)
|
||||
|
|
|
@ -62,6 +62,7 @@ import PaceModalHeading from './heading'
|
|||
import {getSelectedPaceContext} from '../../reducers/pace_contexts'
|
||||
import {getEnrolledSection} from '../../reducers/enrollments'
|
||||
import PaceModalStats from './stats'
|
||||
import {generateModalLauncherId} from '../../utils/utils'
|
||||
|
||||
const I18n = useI18nScope('course_paces_modal')
|
||||
|
||||
|
@ -116,12 +117,18 @@ export const PaceModal: React.FC<PassedProps & DispatchProps & StoreProps> = pro
|
|||
return `${title}: ${props.paceName}`
|
||||
}
|
||||
|
||||
const restoreFocus = () => {
|
||||
const launcherId = generateModalLauncherId(props.selectedPaceContext)
|
||||
document.getElementById(launcherId)?.focus()
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
if (props.unappliedChangesExist) {
|
||||
setPendingContext(props.coursePace.context_type)
|
||||
} else {
|
||||
props.clearCategoryError('publish')
|
||||
props.onClose()
|
||||
restoreFocus()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,6 +230,7 @@ export const PaceModal: React.FC<PassedProps & DispatchProps & StoreProps> = pro
|
|||
props.onResetPace()
|
||||
props.clearCategoryError('publish')
|
||||
props.onClose()
|
||||
restoreFocus()
|
||||
}}
|
||||
contextType={props.coursePace.context_type}
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (C) 2022 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {PaceContext} from '../types'
|
||||
|
||||
export const generateModalLauncherId = (paceContext: PaceContext) =>
|
||||
`pace-modal-launcher-${paceContext.type}-${paceContext.item_id}`
|
Loading…
Reference in New Issue