diff options
author | Tim <timwundenberg@outlook.de> | 2024-12-20 16:39:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-20 23:39:19 +0800 |
commit | 7580bd98c1c9c108500b0c295d5fb6aa057170d4 (patch) | |
tree | 48828986b0c7fbff4068c230dc57e9f5db89d837 | |
parent | 52b319bc00712da095ee4121b616be232b1e455b (diff) | |
download | gitea-7580bd98c1c9c108500b0c295d5fb6aa057170d4.tar.gz gitea-7580bd98c1c9c108500b0c295d5fb6aa057170d4.zip |
show warning on navigation if currently editing comment or title (#32920)
This PR fixes the issue https://github.com/go-gitea/gitea/issues/32223
Make the browser to show the confirm popup, as it does with other forms.
---------
Co-authored-by: Tim Wundenberg <tim@wundenbergs.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
-rw-r--r-- | templates/repo/issue/view_content.tmpl | 8 | ||||
-rw-r--r-- | templates/repo/issue/view_title.tmpl | 10 | ||||
-rw-r--r-- | web_src/js/features/repo-issue-edit.ts | 6 | ||||
-rw-r--r-- | web_src/js/features/repo-issue.ts | 6 | ||||
-rw-r--r-- | web_src/js/vendor/jquery.are-you-sure.ts | 13 |
5 files changed, 27 insertions, 16 deletions
diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl index 69b5a11a14..1a68781ecd 100644 --- a/templates/repo/issue/view_content.tmpl +++ b/templates/repo/issue/view_content.tmpl @@ -139,7 +139,7 @@ </div> <template id="issue-comment-editor-template"> - <div class="ui form comment"> + <form class="ui form comment"> <div class="field"> {{template "shared/combomarkdowneditor" (dict "CustomInit" true @@ -158,11 +158,11 @@ <div class="field"> <div class="text right edit"> - <button class="ui cancel button">{{ctx.Locale.Tr "repo.issues.cancel"}}</button> - <button class="ui primary button">{{ctx.Locale.Tr "repo.issues.save"}}</button> + <button type="button" class="ui cancel button">{{ctx.Locale.Tr "repo.issues.cancel"}}</button> + <button type="submit" class="ui primary button">{{ctx.Locale.Tr "repo.issues.save"}}</button> </div> </div> - </div> + </form> </template> {{template "repo/issue/view_content/reference_issue_dialog" .}} diff --git a/templates/repo/issue/view_title.tmpl b/templates/repo/issue/view_title.tmpl index bf2ede58e4..0354f6ef22 100644 --- a/templates/repo/issue/view_title.tmpl +++ b/templates/repo/issue/view_title.tmpl @@ -26,17 +26,17 @@ </div> </div> {{if $canEditIssueTitle}} - <div class="ui form issue-title tw-hidden" id="issue-title-editor"> + <form class="ui form issue-title tw-hidden" id="issue-title-editor"> <div class="ui input tw-flex-1"> - <input value="{{.Issue.Title}}" data-old-title="{{.Issue.Title}}" maxlength="255" autocomplete="off"> + <input name="title" value="{{.Issue.Title}}" data-old-title="{{.Issue.Title}}" maxlength="255" autocomplete="off"> </div> <div class="issue-title-buttons"> - <button class="ui small basic cancel button">{{ctx.Locale.Tr "repo.issues.cancel"}}</button> - <button class="ui small primary button" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/title"> + <button type="button" class="ui small basic cancel button">{{ctx.Locale.Tr "repo.issues.cancel"}}</button> + <button type="submit" class="ui small primary button" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/title"> {{ctx.Locale.Tr "repo.issues.save"}} </button> </div> - </div> + </form> {{end}} <div class="issue-title-meta"> {{if .HasMerged}} diff --git a/web_src/js/features/repo-issue-edit.ts b/web_src/js/features/repo-issue-edit.ts index 9d146951bd..cf4c223e03 100644 --- a/web_src/js/features/repo-issue-edit.ts +++ b/web_src/js/features/repo-issue-edit.ts @@ -7,6 +7,7 @@ import {attachRefIssueContextPopup} from './contextpopup.ts'; import {initCommentContent, initMarkupContent} from '../markup/content.ts'; import {triggerUploadStateChanged} from './comp/EditorUpload.ts'; import {convertHtmlToMarkdown} from '../markup/html2markdown.ts'; +import {applyAreYouSure, reinitializeAreYouSure} from '../vendor/jquery.are-you-sure.ts'; async function tryOnEditContent(e) { const clickTarget = e.target.closest('.edit-content'); @@ -48,6 +49,7 @@ async function tryOnEditContent(e) { showErrorToast(data.errorMessage); return; } + reinitializeAreYouSure(editContentZone.querySelector('form')); // the form is no longer dirty editContentZone.setAttribute('data-content-version', data.contentVersion); if (!data.content) { renderContent.innerHTML = document.querySelector('#no-content').innerHTML; @@ -86,13 +88,15 @@ async function tryOnEditContent(e) { comboMarkdownEditor = getComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor')); if (!comboMarkdownEditor) { editContentZone.innerHTML = document.querySelector('#issue-comment-editor-template').innerHTML; + const form = editContentZone.querySelector('form'); + applyAreYouSure(form); const saveButton = querySingleVisibleElem<HTMLButtonElement>(editContentZone, '.ui.primary.button'); const cancelButton = querySingleVisibleElem<HTMLButtonElement>(editContentZone, '.ui.cancel.button'); comboMarkdownEditor = await initComboMarkdownEditor(editContentZone.querySelector('.combo-markdown-editor')); const syncUiState = () => saveButton.disabled = comboMarkdownEditor.isUploading(); comboMarkdownEditor.container.addEventListener(ComboMarkdownEditor.EventUploadStateChanged, syncUiState); cancelButton.addEventListener('click', cancelAndReset); - saveButton.addEventListener('click', saveAndRefresh); + form.addEventListener('submit', saveAndRefresh); } // FIXME: ideally here should reload content and attachment list from backend for existing editor, to avoid losing data diff --git a/web_src/js/features/repo-issue.ts b/web_src/js/features/repo-issue.ts index 7541039786..1e1bbd64f0 100644 --- a/web_src/js/features/repo-issue.ts +++ b/web_src/js/features/repo-issue.ts @@ -532,7 +532,7 @@ export function initRepoIssueWipToggle() { export function initRepoIssueTitleEdit() { const issueTitleDisplay = document.querySelector('#issue-title-display'); - const issueTitleEditor = document.querySelector('#issue-title-editor'); + const issueTitleEditor = document.querySelector<HTMLFormElement>('#issue-title-editor'); if (!issueTitleEditor) return; const issueTitleInput = issueTitleEditor.querySelector('input'); @@ -558,7 +558,8 @@ export function initRepoIssueTitleEdit() { const prTargetUpdateUrl = pullDescEditor?.getAttribute('data-target-update-url'); const editSaveButton = issueTitleEditor.querySelector('.ui.primary.button'); - editSaveButton.addEventListener('click', async () => { + issueTitleEditor.addEventListener('submit', async (e) => { + e.preventDefault(); const newTitle = issueTitleInput.value.trim(); try { if (newTitle && newTitle !== oldTitle) { @@ -577,6 +578,7 @@ export function initRepoIssueTitleEdit() { } } } + issueTitleEditor.classList.remove('dirty'); window.location.reload(); } catch (error) { console.error(error); diff --git a/web_src/js/vendor/jquery.are-you-sure.ts b/web_src/js/vendor/jquery.are-you-sure.ts index 9efe783c54..7f0bef8040 100644 --- a/web_src/js/vendor/jquery.are-you-sure.ts +++ b/web_src/js/vendor/jquery.are-you-sure.ts @@ -2,6 +2,7 @@ // Fork of the upstream module. The only changes are: // * use export to make it work with ES6 modules. // * the addition of `const` to make it strict mode compatible. +// * ignore forms with "ignore-dirty" class, ignore hidden forms (closest('.tw-hidden')) /*! * jQuery Plugin: Are-You-Sure (Dirty Form Detection) @@ -161,10 +162,10 @@ export function initAreYouSure($) { if (!settings.silent && !window.aysUnloadSet) { window.aysUnloadSet = true; $(window).bind('beforeunload', function() { - const $dirtyForms = $("form").filter('.' + settings.dirtyClass); - if ($dirtyForms.length == 0) { - return; - } + const $forms = $("form:not(.ignore-dirty)").filter('.' + settings.dirtyClass); + const dirtyFormCount = Array.from($forms).reduce((res, form) => form.closest('.tw-hidden') ? res : res + 1, 0); + if (dirtyFormCount === 0) return; + // Prevent multiple prompts - seen on Chrome and IE if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) { if (window.aysHasPrompted) { @@ -199,3 +200,7 @@ export function initAreYouSure($) { export function applyAreYouSure(selectorOrEl: string|Element|$, opts = {}) { $(selectorOrEl).areYouSure(opts); } + +export function reinitializeAreYouSure(selectorOrEl: string|Element|$) { + $(selectorOrEl).trigger('reinitialize.areYouSure'); +} |