mirror of
https://github.com/go-gitea/gitea.git
synced 2025-12-21 19:41:33 +00:00
Show edit page confirmation dialog on tree view file change (#36130)
Currently, when editing or deleting a file and the edit/commit form has changes, navigating the file tree will discard all changes without any warning. This PR prevents partial reloading when the edit form has unsaved changes, which will trigger a browser native warning dialog. --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {SvgIcon} from '../svg.ts';
|
import {SvgIcon} from '../svg.ts';
|
||||||
import {isPlainClick} from '../utils/dom.ts';
|
import {isPlainClick} from '../utils/dom.ts';
|
||||||
|
import {shouldTriggerAreYouSure} from '../vendor/jquery.are-you-sure.ts';
|
||||||
import {shallowRef} from 'vue';
|
import {shallowRef} from 'vue';
|
||||||
import type {createViewFileTreeStore, FileTreeItem} from './ViewFileTreeStore.ts';
|
import type {createViewFileTreeStore, FileTreeItem} from './ViewFileTreeStore.ts';
|
||||||
|
|
||||||
@@ -27,9 +28,10 @@ const doLoadChildren = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onItemClick = (e: MouseEvent) => {
|
const onItemClick = (e: MouseEvent) => {
|
||||||
// only handle the click event with page partial reloading if the user didn't press any special key
|
// only handle the click event with partial page reloading if both
|
||||||
// let browsers handle special keys like "Ctrl+Click"
|
// - the user didn't press any special key like "Ctrl+Click" (which may have custom browser behavior)
|
||||||
if (!isPlainClick(e)) return;
|
// - the editor/commit form isn't dirty (a full page reload shows a confirmation dialog if the form contains unsaved changes)
|
||||||
|
if (!isPlainClick(e) || shouldTriggerAreYouSure()) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (props.item.entryMode === 'tree') doLoadChildren();
|
if (props.item.entryMode === 'tree') doLoadChildren();
|
||||||
store.navigateTreeView(props.item.fullPath);
|
store.navigateTreeView(props.item.fullPath);
|
||||||
|
|||||||
21
web_src/js/vendor/jquery.are-you-sure.ts
vendored
21
web_src/js/vendor/jquery.are-you-sure.ts
vendored
@@ -3,6 +3,7 @@
|
|||||||
// * use export to make it work with ES6 modules.
|
// * use export to make it work with ES6 modules.
|
||||||
// * the addition of `const` to make it strict mode compatible.
|
// * the addition of `const` to make it strict mode compatible.
|
||||||
// * ignore forms with "ignore-dirty" class, ignore hidden forms (closest('.tw-hidden'))
|
// * ignore forms with "ignore-dirty" class, ignore hidden forms (closest('.tw-hidden'))
|
||||||
|
// * extract the dirty check logic into a separate function
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* jQuery Plugin: Are-You-Sure (Dirty Form Detection)
|
* jQuery Plugin: Are-You-Sure (Dirty Form Detection)
|
||||||
@@ -16,6 +17,9 @@
|
|||||||
* Version: 1.9.0
|
* Version: 1.9.0
|
||||||
* Date: 13th August 2014
|
* Date: 13th August 2014
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const dataKeyAysSettings = 'ays-settings';
|
||||||
|
|
||||||
export function initAreYouSure($) {
|
export function initAreYouSure($) {
|
||||||
|
|
||||||
$.fn.areYouSure = function(options) {
|
$.fn.areYouSure = function(options) {
|
||||||
@@ -124,6 +128,7 @@ export function initAreYouSure($) {
|
|||||||
$(fields).unbind(settings.fieldEvents, checkForm);
|
$(fields).unbind(settings.fieldEvents, checkForm);
|
||||||
$(fields).bind(settings.fieldEvents, checkForm);
|
$(fields).bind(settings.fieldEvents, checkForm);
|
||||||
$form.data("ays-orig-field-count", $(fields).length);
|
$form.data("ays-orig-field-count", $(fields).length);
|
||||||
|
$form.data(dataKeyAysSettings, settings);
|
||||||
setDirtyStatus($form, false);
|
setDirtyStatus($form, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -162,9 +167,7 @@ export function initAreYouSure($) {
|
|||||||
if (!settings.silent && !window.aysUnloadSet) {
|
if (!settings.silent && !window.aysUnloadSet) {
|
||||||
window.aysUnloadSet = true;
|
window.aysUnloadSet = true;
|
||||||
$(window).bind('beforeunload', function() {
|
$(window).bind('beforeunload', function() {
|
||||||
const $forms = $("form:not(.ignore-dirty)").filter('.' + settings.dirtyClass);
|
if (!shouldTriggerAreYouSure(settings)) return;
|
||||||
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
|
// Prevent multiple prompts - seen on Chrome and IE
|
||||||
if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) {
|
if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) {
|
||||||
@@ -210,3 +213,15 @@ export function ignoreAreYouSure(selectorOrEl: string|Element|$) {
|
|||||||
// because when using "enter" to submit a form, the "dirty" class will appear again before reloading.
|
// because when using "enter" to submit a form, the "dirty" class will appear again before reloading.
|
||||||
$(selectorOrEl).addClass('ignore-dirty');
|
$(selectorOrEl).addClass('ignore-dirty');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shouldTriggerAreYouSure(): boolean {
|
||||||
|
const forms = document.querySelectorAll('form:not(.ignore-dirty)');
|
||||||
|
for (const form of forms) {
|
||||||
|
const settings = $(form).data(dataKeyAysSettings);
|
||||||
|
if (!settings) continue;
|
||||||
|
if (!form.matches('.' + settings.dirtyClass)) continue;
|
||||||
|
if (form.closest('.tw-hidden')) continue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user