Show overlay and disable buttons while saving

closes VICE-4124
flag=discussion_create

test plan:
 - Specs pass
 - Go to the Discussion Create/Edit page
 - Try creating a discussion topic
 - Loading overlay should appear and buttons
     should be disabled.
 - Try causing a back-end error and see that
     overlay goes away. To force this to happen,
     simply go to the CreateDiscussionTopic mutation
     and add an early:
       return validation_error("Hi!")

Change-Id: I610243eb334ae66baddea0d8357d70204baf83ae
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/340628
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Chawn Neal <chawn.neal@instructure.com>
QA-Review: Jason Gillett <jason.gillett@instructure.com>
Product-Review: Omar Soto-Fortuño <omar.soto@instructure.com>
This commit is contained in:
Omar Gerardo Soto-Fortuño 2024-02-15 16:40:59 -05:00 committed by Omar Soto-Fortuño
parent 38b63a0b7a
commit f59d0736c7
3 changed files with 72 additions and 2 deletions

View File

@ -57,6 +57,7 @@ import {
} from '../../util/utils'
import {MissingSectionsWarningModal} from '../MissingSectionsWarningModal/MissingSectionsWarningModal'
import {flushSync} from 'react-dom'
import {SavingDiscussionTopicOverlay} from '../SavingDiscussionTopicOverlay/SavingDiscussionTopicOverlay'
const I18n = useI18nScope('discussion_create')
@ -71,6 +72,8 @@ export default function DiscussionTopicForm({
onSubmit,
isGroupContext,
apolloClient,
isSubmitting,
setIsSubmitting,
}) {
const rceRef = useRef()
const textInputRef = useRef()
@ -635,11 +638,20 @@ export default function DiscussionTopicForm({
}
const continueSubmitForm = shouldPublish => {
setTimeout(() => {
setIsSubmitting(true)
}, 0)
if (validateFormFields()) {
const payload = createSubmitPayload(shouldPublish)
onSubmit(payload)
return true
}
setTimeout(() => {
setIsSubmitting(false)
}, 0)
return false
}
@ -1178,6 +1190,7 @@ export default function DiscussionTopicForm({
onClick={() => {
window.location.assign(ENV.CANCEL_TO)
}}
disabled={isSubmitting}
>
{I18n.t('Cancel')}
</Button>
@ -1190,6 +1203,7 @@ export default function DiscussionTopicForm({
color="secondary"
margin="xxx-small"
data-testid="save-and-publish-button"
disabled={isSubmitting}
>
{I18n.t('Save and Publish')}
</Button>
@ -1204,6 +1218,7 @@ export default function DiscussionTopicForm({
color="primary"
margin="xxx-small"
data-testid="announcement-submit-button"
disabled={isSubmitting}
>
{willAnnouncementPostRightAway ? I18n.t('Publish') : I18n.t('Save')}
</Button>
@ -1218,6 +1233,7 @@ export default function DiscussionTopicForm({
submitForm(isEditing ? published : !ENV.DISCUSSION_TOPIC?.PERMISSIONS?.CAN_MODERATE)
}
color="primary"
disabled={isSubmitting}
>
{I18n.t('Save')}
</Button>
@ -1234,6 +1250,7 @@ export default function DiscussionTopicForm({
}}
/>
)}
<SavingDiscussionTopicOverlay open={isSubmitting} />
</>
)
}
@ -1249,6 +1266,8 @@ DiscussionTopicForm.propTypes = {
onSubmit: PropTypes.func,
isGroupContext: PropTypes.bool,
apolloClient: PropTypes.object,
isSubmitting: PropTypes.bool,
setIsSubmitting: PropTypes.func,
}
DiscussionTopicForm.defaultProps = {
@ -1258,4 +1277,6 @@ DiscussionTopicForm.defaultProps = {
sections: [],
groupCategories: [],
onSubmit: () => {},
isSubmitting: false,
setIsSubmitting: () => {},
}

View File

@ -0,0 +1,42 @@
// @ts-nocheck
/*
* Copyright (C) 2024 - 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 React from 'react'
import {Spinner} from '@instructure/ui-spinner'
import {useScope as useI18nScope} from '@canvas/i18n'
import {Mask, Overlay} from '@instructure/ui-overlays'
const I18n = useI18nScope('discussion_create')
type Props = {
open: boolean
}
export const SavingDiscussionTopicOverlay = ({open}: Props) => {
const label = I18n.t('Loading')
const message = I18n.t('Saving Discussion Topic')
return (
<Overlay open={open} transition="fade" label={message}>
<Mask themeOverride={{zIndex: 10001}} fullscreen={true}>
<Spinner renderTitle={label} size="large" margin="0 0 0 medium" />
</Mask>
</Overlay>
)
}

View File

@ -33,6 +33,7 @@ const I18n = useI18nScope('discussion_create')
export default function DiscussionTopicFormContainer({apolloClient}) {
const {setOnFailure} = useContext(AlertManagerContext)
const [usageRightData, setUsageRightData] = useState()
const [isSubmitting, setIsSubmitting] = useState(false)
const contextType = ENV.context_is_not_group ? 'Course' : 'Group'
const {contextQueryToUse, contextQueryVariables} = getContextQuery(contextType)
@ -107,25 +108,28 @@ export default function DiscussionTopicFormContainer({apolloClient}) {
navigateToDiscussionTopic(discussionContextType, discussionTopicId)
}
} else {
setIsSubmitting(false)
setOnFailure(I18n.t('Error with discussion topic'))
}
}
const [createDiscussionTopic] = useMutation(CREATE_DISCUSSION_TOPIC, {
onCompleted: completionData => {
const new_discussion_topic = completionData?.createDiscussionTopic?.discussionTopic
const newDiscussionTopic = completionData?.createDiscussionTopic?.discussionTopic
const errors = completionData?.createDiscussionTopic?.errors
if (errors) {
setIsSubmitting(false)
setOnFailure(errors.map(error => error.message).join(', '))
return
}
handleDiscussionTopicMutationCompletion(new_discussion_topic).catch(() => {
handleDiscussionTopicMutationCompletion(newDiscussionTopic).catch(() => {
setOnFailure(I18n.t('Error updating file usage rights'))
})
},
onError: () => {
setIsSubmitting(false)
setOnFailure(I18n.t('Error creating discussion topic'))
},
})
@ -139,6 +143,7 @@ export default function DiscussionTopicFormContainer({apolloClient}) {
})
},
onError: () => {
setIsSubmitting(false)
setOnFailure(I18n.t('Error updating discussion topic'))
},
})
@ -159,6 +164,8 @@ export default function DiscussionTopicFormContainer({apolloClient}) {
studentEnrollments={currentContext?.usersConnection?.nodes}
apolloClient={apolloClient}
onSubmit={handleFormSubmit}
isSubmitting={isSubmitting}
setIsSubmitting={setIsSubmitting}
/>
)
}