Fix Sync to SIS in embedded Assign To for discussions

closes LX-1952

flag=selective_release_ui_api
flag=selective_release_edit_page

test plan:
- Enable required sync to SIS and make due
dates required in account settings.
- Navigate to a graded discussion create/edit page.
> Verify that if the Sync to SIS checkbox is enabled
the cards of the panel should require due dates
(showing errors). If not you can leave these fields
blank.
> Verify that you are not able to save if there
are empty due dates if Sync to SIS is enabled.
> Verify that if you try to Save, the focus will
go to the first issue you have on the cards.

Change-Id: Ic844d45aa477e41cd6d406cb3ed5f0c83817f551
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/354840
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Sarah Gerard <sarah.gerard@instructure.com>
QA-Review: Sarah Gerard <sarah.gerard@instructure.com>
Product-Review: Juan Chavez <juan.chavez@instructure.com>
This commit is contained in:
juan.chavez 2024-08-12 18:42:51 -04:00 committed by Juan Chavez
parent b37258f970
commit e34441901e
1 changed files with 56 additions and 19 deletions

View File

@ -131,6 +131,8 @@ function DiscussionTopicForm({
const dateInputRef = useRef() const dateInputRef = useRef()
const groupOptionsRef = useRef() const groupOptionsRef = useRef()
const gradedDiscussionRef = useRef() const gradedDiscussionRef = useRef()
const shouldForceFocusAfterRenderRef = useRef(false)
const postToSisForCards = useRef(!!currentDiscussionTopic?.assignment?.postToSis || false)
const {setOnFailure} = useContext(AlertManagerContext) const {setOnFailure} = useContext(AlertManagerContext)
const isAnnouncement = ENV?.DISCUSSION_TOPIC?.ATTRIBUTES?.is_announcement ?? false const isAnnouncement = ENV?.DISCUSSION_TOPIC?.ATTRIBUTES?.is_announcement ?? false
@ -190,7 +192,10 @@ function DiscussionTopicForm({
currentDiscussionTopic?.isAnonymousAuthor || true currentDiscussionTopic?.isAnonymousAuthor || true
) )
const [isThreaded, setIsThreaded] = useState( const [isThreaded, setIsThreaded] = useState(
currentDiscussionTopic?.discussionType === "threaded" || (currentDiscussionTopic?.discussionType === "side_comment" && ENV?.DISCUSSION_TOPIC?.ATTRIBUTES?.has_threaded_replies) || Object.keys(currentDiscussionTopic).length === 0 currentDiscussionTopic?.discussionType === 'threaded' ||
(currentDiscussionTopic?.discussionType === 'side_comment' &&
ENV?.DISCUSSION_TOPIC?.ATTRIBUTES?.has_threaded_replies) ||
Object.keys(currentDiscussionTopic).length === 0
) )
const [requireInitialPost, setRequireInitialPost] = useState( const [requireInitialPost, setRequireInitialPost] = useState(
currentDiscussionTopic?.requireInitialPost || false currentDiscussionTopic?.requireInitialPost || false
@ -340,9 +345,25 @@ function DiscussionTopicForm({
pointsPossible, pointsPossible,
isGraded, isGraded,
isCheckpoints, isCheckpoints,
postToSis, postToSis: ENV.FEATURES.selective_release_edit_page ? postToSisForCards.current : postToSis,
} }
useEffect(() => {
// Expects to force the focus the errors on re-render once
if (
shouldForceFocusAfterRenderRef.current &&
ENV.FEATURES.selective_release_ui_api &&
ENV.FEATURES.selective_release_edit_page
) {
const sectionViewRef = document.getElementById(
'manage-assign-to-container'
)?.reactComponentInstance
if (sectionViewRef?.focusErrors()) {
shouldForceFocusAfterRenderRef.current = false
}
}
})
useEffect(() => { useEffect(() => {
if (isAnnouncement && availableFrom) { if (isAnnouncement && availableFrom) {
const rightNow = new Date() const rightNow = new Date()
@ -476,11 +497,7 @@ function DiscussionTopicForm({
...(shouldShowUsageRightsOption && {usageRightsData}), ...(shouldShowUsageRightsOption && {usageRightsData}),
} }
if ( if (!isGraded && ENV.FEATURES?.selective_release_ui_api && !isAnnouncement) {
!isGraded &&
ENV.FEATURES?.selective_release_ui_api &&
!isAnnouncement
) {
delete payload.specificSections delete payload.specificSections
Object.assign( Object.assign(
payload, payload,
@ -532,6 +549,7 @@ function DiscussionTopicForm({
const continueSubmitForm = (shouldPublish, shouldNotifyUsers = false) => { const continueSubmitForm = (shouldPublish, shouldNotifyUsers = false) => {
setTimeout(() => { setTimeout(() => {
postToSisForCards.current = postToSis
setIsSubmitting(true) setIsSubmitting(true)
}, 0) }, 0)
@ -560,7 +578,7 @@ function DiscussionTopicForm({
sectionIdsToPostTo, sectionIdsToPostTo,
assignedInfoList, assignedInfoList,
postToSis, postToSis,
showPostToSisFlashAlert('manage-assign-to', true) showPostToSisFlashAlert('manage-assign-to', !ENV.FEATURES.selective_release_edit_page)
) )
) { ) {
const payload = createSubmitPayload(shouldPublish) const payload = createSubmitPayload(shouldPublish)
@ -569,6 +587,23 @@ function DiscussionTopicForm({
} }
setTimeout(() => { setTimeout(() => {
if (
isGraded &&
ENV.DUE_DATE_REQUIRED_FOR_ACCOUNT &&
ENV.FEATURES.selective_release_ui_api &&
ENV.FEATURES.selective_release_edit_page &&
assignedInfoList.length > 0 &&
postToSis
) {
const sectionViewRef = document.getElementById(
'manage-assign-to-container'
)?.reactComponentInstance
const aDueDateMissing = assignedInfoList.some(assignee => !assignee.dueDate)
// If there are errors visible already don't force the focus
if (sectionViewRef?.allCardsValid() && aDueDateMissing) {
shouldForceFocusAfterRenderRef.current = true
}
}
setIsSubmitting(false) setIsSubmitting(false)
}, 0) }, 0)
@ -1097,13 +1132,18 @@ function DiscussionTopicForm({
)} )}
</View> </View>
)} )}
{!canGroupDiscussion && isEditing && !isAnnouncement && currentDiscussionTopic?.entryCounts?.repliesCount > 0 && ( {!canGroupDiscussion &&
<View display="block" data-testid="group-category-not-editable"> isEditing &&
<Alert variant="warning" margin="small none small none"> !isAnnouncement &&
{I18n.t('Students have already submitted to this discussion, so group settings cannot be changed.')} currentDiscussionTopic?.entryCounts?.repliesCount > 0 && (
</Alert> <View display="block" data-testid="group-category-not-editable">
</View> <Alert variant="warning" margin="small none small none">
)} {I18n.t(
'Students have already submitted to this discussion, so group settings cannot be changed.'
)}
</Alert>
</View>
)}
</FormFieldGroup> </FormFieldGroup>
{discussionAnonymousState.includes('anonymity') && !isEditing && ( {discussionAnonymousState.includes('anonymity') && !isEditing && (
<View width="580px" display="block" data-testid="groups_grading_not_allowed"> <View width="580px" display="block" data-testid="groups_grading_not_allowed">
@ -1121,10 +1161,7 @@ function DiscussionTopicForm({
</div> </div>
<div style={{display: selectedView === Views.MasteryPaths ? 'block' : 'none'}}> <div style={{display: selectedView === Views.MasteryPaths ? 'block' : 'none'}}>
{ENV.CONDITIONAL_RELEASE_ENV && ( {ENV.CONDITIONAL_RELEASE_ENV && (
<MasteryPathsReactWrapper <MasteryPathsReactWrapper type="discussion topic" env={ENV.CONDITIONAL_RELEASE_ENV} />
type="discussion topic"
env={ENV.CONDITIONAL_RELEASE_ENV}
/>
)} )}
</div> </div>
<FormFieldGroup description="" rowSpacing="small"> <FormFieldGroup description="" rowSpacing="small">