diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2023-11-21 10:12:31 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-21 02:12:31 +0000 |
commit | 247927a9b51cea88db6f7d2dee25471339feb51b (patch) | |
tree | 2158b212fdb89eb337303d495b2e8870393949fd /web_src | |
parent | 0c72256ab4e6e6f6c6cd6d4949b37d32a7816785 (diff) | |
download | gitea-247927a9b51cea88db6f7d2dee25471339feb51b.tar.gz gitea-247927a9b51cea88db6f7d2dee25471339feb51b.zip |
Use "is-loading" to avoid duplicate form submit for code comment (#28143)
When the form is going to be submitted, add the "is-loading" class to
show an indicator and avoid user UI events.
When the request finishes (success / error), remove the "is-loading"
class to make user can interact the UI.
Diffstat (limited to 'web_src')
-rw-r--r-- | web_src/js/features/repo-diff.js | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/web_src/js/features/repo-diff.js b/web_src/js/features/repo-diff.js index 864b28a3bb..e74db04d08 100644 --- a/web_src/js/features/repo-diff.js +++ b/web_src/js/features/repo-diff.js @@ -6,8 +6,9 @@ import {initDiffCommitSelect} from './repo-diff-commitselect.js'; import {validateTextareaNonEmpty} from './comp/ComboMarkdownEditor.js'; import {initViewedCheckboxListenerFor, countAndUpdateViewedFiles, initExpandAndCollapseFilesButton} from './pull-view-file.js'; import {initImageDiff} from './imagediff.js'; +import {showErrorToast} from '../modules/toast.js'; -const {csrfToken, pageData} = window.config; +const {csrfToken, pageData, i18n} = window.config; function initRepoDiffReviewButton() { const $reviewBox = $('#review-box'); @@ -50,26 +51,34 @@ function initRepoDiffConversationForm() { return; } - const formData = new FormData($form[0]); + if ($form.hasClass('is-loading')) return; + try { + $form.addClass('is-loading'); + const formData = new FormData($form[0]); - // if the form is submitted by a button, append the button's name and value to the form data - const submitter = e.originalEvent?.submitter; - const isSubmittedByButton = (submitter?.nodeName === 'BUTTON') || (submitter?.nodeName === 'INPUT' && submitter.type === 'submit'); - if (isSubmittedByButton && submitter.name) { - formData.append(submitter.name, submitter.value); - } - const formDataString = String(new URLSearchParams(formData)); - const $newConversationHolder = $(await $.post($form.attr('action'), formDataString)); - const {path, side, idx} = $newConversationHolder.data(); - - $form.closest('.conversation-holder').replaceWith($newConversationHolder); - if ($form.closest('tr').data('line-type') === 'same') { - $(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).addClass('gt-invisible'); - } else { - $(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).addClass('gt-invisible'); + // if the form is submitted by a button, append the button's name and value to the form data + const submitter = e.originalEvent?.submitter; + const isSubmittedByButton = (submitter?.nodeName === 'BUTTON') || (submitter?.nodeName === 'INPUT' && submitter.type === 'submit'); + if (isSubmittedByButton && submitter.name) { + formData.append(submitter.name, submitter.value); + } + const formDataString = String(new URLSearchParams(formData)); + const $newConversationHolder = $(await $.post($form.attr('action'), formDataString)); + const {path, side, idx} = $newConversationHolder.data(); + + $form.closest('.conversation-holder').replaceWith($newConversationHolder); + if ($form.closest('tr').data('line-type') === 'same') { + $(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).addClass('gt-invisible'); + } else { + $(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).addClass('gt-invisible'); + } + $newConversationHolder.find('.dropdown').dropdown(); + initCompReactionSelector($newConversationHolder); + } catch { // here the caught error might be a jQuery AJAX error (thrown by await $.post), which is not good to use for error message handling + showErrorToast(i18n.network_error); + } finally { + $form.removeClass('is-loading'); } - $newConversationHolder.find('.dropdown').dropdown(); - initCompReactionSelector($newConversationHolder); }); $(document).on('click', '.resolve-conversation', async function (e) { |